SMTP on C#

この記事は古いです。ここも参照してください


.net framewor2.0に元からあるSMTPClient(だっけ?)だと僕がやりたいことができないので、SocketとかSMTPコマンドとか勉強して作ってみた。

うししこれで…


ソースは続きに書いてあります。
ライセンスとか良く知らないのですが…なんかまずいかな…
まずいよねきっとw
著作権は放棄しませんが、自由に使ってくださって結構です。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;

namespace SMTP
{
    class Program
    {
        static void Main(string[] args)
        {
            SMTP smtp = new SMTP("127.0.0.1");

            //送信者のメールアドレス
            smtp.From("aont@from.com");

            //実際の送信先
            smtp.Recipient("aont@recipient.com");

            SMTP.Message Mes = new SMTP.Message();

            Mes.From = new SMTP.Address("aont@from.com", "送信者");

            Mes.To = new List<SMTP.Address>();
            Mes.To.Add(new SMTP.Address("aont@recipient.com", "送信先(見せ掛け)"));

            Mes.Subject = "件名";
            Mes.Body = "本文";

            smtp.Send(Mes);

            smtp.Quit();

            Console.ReadKey(true);
        }
    }




    class SMTP
    {
        NetworkStream Stream;
        TcpClient Client;
        int Port;
        string Server;
        StreamReader Reader;

        public SMTP(string Server, int Port)
        {
            this.Server = Server;
            this.Port = Port;
            Connect();
        }

        public SMTP(string Server)
        {
            this.Server = Server;
            this.Port = 25;
            Connect();
        }

        void Connect()
        {
            Client = new TcpClient(Server, Port);
            Stream = Client.GetStream();
            Stream.ReadTimeout = 5;
            Reader = new StreamReader(Stream);

            ReadEx("220");
            WriteLine("HELO ", Server);
            ReadEx("250");

        }

        ~SMTP()
        {
            try
            {
                Quit();
            }
            catch { }
        }

        string ReadEx(params string[] codes)
        {
            string read = Read();

            Console.WriteLine(read);
            foreach (string code in codes)
            {
                if (read.StartsWith(code))
                    return read;
            }
            throw new Exception(read);
        }

        string Read()
        {
            return Reader.ReadLine();
        }

        void Write(byte[] bytearray)
        {
            Stream.Write(bytearray, 0, bytearray.Length);
        }
        void Write(byte[] bytearray, int offset, int size)
        {
            Stream.Write(bytearray, offset, size);
        }
        void Write(string write)
        {
            byte[] bytearray = System.Text.Encoding.UTF8.GetBytes(write);
            Write(bytearray);
        }
        void WriteLine(string write)
        {
            Write(write);
            Stream.Write(new byte[] { 13, 10 }, 0, 2);
        }
        void Write(params string[] write_array)
        {
            foreach (string write in write_array)
            {
                Write(write);
            }
        }
        void WriteLine(params string[] write_array)
        {
            foreach (string write in write_array)
            {
                Write(write);
            }
            Stream.Write(new byte[] { 13, 10 }, 0, 2);
        }

        public void From(string from)
        {
            WriteLine("MAIL FROM:<", from, ">");
            ReadEx("250");
        }

        public void Recipient(string rcpt)
        {
            WriteLine("RCPT TO:<", rcpt, ">");
            ReadEx("250", "251");
        }

        public void Send(Message message)
        {
            WriteLine("DATA");
            ReadEx("250", "354");
            Write(message.ToString());
            WriteLine("\r\n.");
            ReadEx("250");
        }

        public void Quit()
        {
            WriteLine("QUIT");
            ReadEx("221");

            Reader.Dispose();
            Stream.Dispose();
        }

        static string ToBase64(byte[] bytes)
        {
            return Convert.ToBase64String(bytes);
        }

        static string ToBase64(string @string)
        {
            return Convert.ToBase64String(
                jisEnc.GetBytes(
                    @string
                )
            );
        }

        static Encoding jisEnc = Encoding.GetEncoding(50220);
        static string ToBase64jis(string @string)
        {
            byte[] bytes = jisEnc.GetBytes(@string);

            return "=?ISO-2022-JP?B?" + ToBase64(bytes) + "?=";
        }

        public class Message
        {
            public Address From;

            public List<Address> To;
            /*
            public List<Address> Cc;
            public List<Address> Bcc;
            public Address ReplyTo;
            */
            public string Subject;
            public byte[] Data;

            public string Body
            {
                set
                {
                    Data = jisEnc.GetBytes(value);
                }
                get
                {
                    return jisEnc.GetString(Data);
                }
            }

            public override string ToString()
            {
                string @string = "";

                @string += "From: " + From + "\r\n";

                @string += "To: ";
                foreach (Address to in To)
                {
                    @string += to;
                    @string += ",";
                }
                @string += "\r\n";

                @string += "Subject: " + ToBase64jis(Subject) + "\r\n";

                @string += "MIME-Version: 1.0\r\n";
                @string += "X-Mail-Agent: Aont Mailer\r\n";

                @string += "Content-Type: text/plain; charset=ISO-2022-JP\r\n";
                @string += "Content-Transfer-Encoding: base64\r\n";
                @string += "\r\n";

                @string += ToBase64(Data);

                return @string;
            }
        }


        public class Address
        {
            public string address;
            public string name;

            public override string ToString()
            {
                return ToBase64jis(name) + "<" + address + ">";
            }

            public Address(string address, string name)
            {
                this.address = address;
                this.name = name;
            }


        }
    }
}


パスワードが必要なサーバへの接続方法は資料がまだ見つかってなくて、作れてない。
HTML形式とか添付ファイルとかもいつかできるようにしておこう。


Visual C#のすばらしいデバッグ機能がなければ今頃デバッグに苦しんでいたところであろう…


GUIは作っても良いけど、にの次だ。


前の日記読んだら…
自分はCでDLL作ってC#で読み込ませる予定だったのか…
まぁこっちのほうがスマートだから結果All Rightと思う。



クラスの構造は今は

  • SMTP
    • Message
    • Adress

だけど、

  • Mail
    • SMTP
    • Message
    • Address

って感じにしたほうが良いかもって思った。


Radishには大変お世話になりましたw