CLX C++ Libraries - smtp
Author: clown

CLX C++ Libraries
Home >> smtp

# Declaration

    template <class Socket>
    class basic_smtp : public Socket;

    typedef basic_smtp<tcp::socket> smtp;

    namespace smtp_auth {
        enum {
            none     = 0x01,
            plain    = 0x02,
            login    = 0x04,
            cram_md5 = 0x08,
            best     = 0x0f
        };
    }

# Overview

smtp クラスは SMTP (Simple Mail Transfer Protocol) でメールを送信するためのクラスです． start() メソッドでメールサーバと接続し，login() メソッドでログイン処理を行った後， mail() メソッドで実際にメールを送信します．login() メソッドは現在のところ PLAIN, LOGIN, CRAM-MD5 方式に対応しており，どの方式を用いるかを login() メソッドの第 3 引数に指定します．

smtp クラスは，サーバからエラーメッセージが返された場合には smtp_error を例外として送出します． また，smtp クラスはサーバからの応答メッセージを内部に蓄積するように実装しています． response() メソッドを呼ぶと，サーバからの応答メッセージの一覧を取得することができます．

# Example

example_smtp.cpp

    #include <iostream>
    #include <string>
    #include <sstream>
    #include "clx/smtp.h"
    #include "clx/date_time.h"

    int main(int argc, char* argv[]) {
        if (argc < 6) {
            std::cerr << "usage " << argv[0] << " host id pass from to" << std::endl;
            std::exit(-1);
        }

        try {
            clx::smtp session(argv[1], 25);

            /*
             * 第3引数でSMTP-AUTH の方法を指定する．
             *   - clx::smtp_auth::plain
             *   - clx::smtp_auth::login
             *   - clx::smtp_auth::cram_md5
             *
             * clx::smtp_auth::none を指定すると SMTP-AUTH は行わずに EHLO パケット
             * を送信するのみ．clx::smtp_auth::best を指定すると，
             * cram_md5 -> plain -> login の順番でサーバがサポートしているかどうか
             * 調べ，最初にサポートしていた方式で認証を行う．いずれにも対応していない
             * 場合は，clx::smtp_auth::none を指定した場合と同じ．
             *
             * 第3引数の省略時は，clx::smtp_auth::best．
             */
            session.login(argv[2], argv[3]);

            std::string from(argv[4]);
            std::string to(argv[5]);

            // create a sample message
            std::stringstream msg;
            clx::date_time now;
            msg << "Date: " << now.to_string<char>("%a, %d %b %Y %H:%M:%S +0900") << "\r\n";
            msg << "From: " << from << "\r\n";
            msg << "To: " << to << "\r\n";
            msg << "Subject: SMTP test mail\r\n";
            msg << "\r\n";
            msg << "This ia test mail for clx::smtp class.\r\n";
            msg << ".\r\n";
            session.mail(from, to, msg.str());
            session.finish();

            // print message log
            for (size_t i = 0; i < session.responses().size(); i++) {
                std::cout << session.response(i).first << ": " <<
                    session.response(i).second << std::endl;
            }
        }
        catch (clx::smtp_error& e) {
            std::cerr << e.code() << ": " << e.what() << std::endl;
            std::exit(-1);
        }
        catch (clx::socket_error& e) {
            std::cerr << e.what() << std::endl;
            std::exit(-1);
        }
        catch (std::runtime_error& e) {
            std::cerr << e.what() << std::endl;
            std::exit(-1);
        }

        return 0;
    }

    Result
    221: s273.xrea.com
    250: ok 1225262277 qp 10527
    354: go ahead
    250: ok
    250: ok
    235: ok, go ahead (#2.0.0)
    334: PDEwNTA2LjEyMjUyNjIyNzdAczI3My54cmVhLmNvbT4=
    250: 8BITMIME
    250: PIPELINING
    250: AUTH=LOGIN CRAM-MD5 PLAIN
    250: AUTH LOGIN CRAM-MD5 PLAIN
    250: s273.xrea.com
    220: s273.xrea.com ESMTP

# Template Parameters

Socket
  ソケットクラスを指定します．

# Related Types

    typedef Socket socket_type;
    typedef char char_type;
    typedef std::basic_string<char_type> string_type;

    typedef std::pair<int, string_type> response_type;
    typedef std::deque<response_type> response_array;

# Construction and Member Functions

    basic_smtp();
    basic_smtp(const basic_smtp& cp);
    explicit basic_smtp(const string_type& host, int port = 25);
    explicit basic_smtp(const char_type* host, int port = 25);
    virtual ~basic_smtp();

    basic_smtp& start();
    basic_smtp& start(const string_type& host, int port = 25);
    basic_smtp& start(const char_type* host, int port = 25);

    void finish();

    basic_smtp& login(const string_type& id);
    basic_smtp& login(const char_type* id);

    basic_smtp& login(const string_type& id, const string_type& pass,
        int type = smtp_auth::best);
    basic_smtp& login(const char_type* id, const char_type* pass,
        int type = smtp_auth::best);

start() メソッドで SMTP サーバと接続し，login() メソッドでログイン処理を行います． login() の第 3 引数として指定できる値は，smtp_auth::none, smtp_auth::plain, smtp_auth::login, smtp_auth::cram_md5, smtp_auth::best の 5 種類です．

clx::smtp_auth::none を指定すると SMTP-AUTH は行わずに EHLO パケットを送るのみで login() を終了します．smtp_auth::plain, smtp_auth::login, smtp_auth::cram_md5 を指定すると，それぞれ PLAIN, LOGIN, CRAM-MD 方式で認証を試みます． smtp_auth::best を指定すると，CRAM-MD5, PLAIN, LOGIN の順序でサーバがその認証方式を サポートしているかどうか調べ，最初に見つけた方式で認証を行います． いずれの方式にも対応していない場合は，clx::smtp_auth::none を指定した場合と同じ挙動になります．

login() メソッドの第 3 引数を省略した場合は smtp_auth::best が指定されたと見なされます．

    basic_smtp& mail(const string_type& from, const string_type& to,
        const string_type& message);
    basic_smtp& mail(const char_type* from, const char_type* to,
        const char_type* message);

実際にメールを送信するときは，送信元，宛先，メールの内容を引数として指定し mail() メソッドを実行します．

    response_array& responses();
    const response_array& responses() const;
    const response_type& response(size_t index) const;

response() メソッドは，SMTP サーバからの応答メッセージの一覧を取得するためのメソッドです． それぞれの応答メッセージ (response_type) は，応答コードとメッセージのペアで構成されています． サーバからの応答メッセージはキュー (正確には std::deque) で管理しているため， 最新のメッセージが先頭に格納されています．

# Related Page

1. CLX C++ Libraries - smtps