C # Mail sending problem (i)

Source: Internet
Author: User
Tags imap rfc starttls mailmessage smtpclient



There are a number of factors to consider when sending mail, including sending mail clients (generic encoding implementations), sending and receiving mail server settings, and so on. If you use a third-party mail server as the sending server, you need to consider the sending limits for that server, such as sending the message interval, the number of messages sent per unit of time, and whether to use secure connection SSL, as well as the limitations of the incoming mail server regardless of whether you use a third party or your own mail server. To clarify the idea, here we briefly review the basic network structure of the e-mail system and the mail sending and receiving process.



First, the basic network structure of e-mail system



Such as:






Mail send receive generally passes through the following several nodes:


    • Send mail client (mail User Agent, MUA): Formail, Outlook, Webmail, C # code, Java code, etc.
    • Outgoing mail server (mail Transfer Agent, MTA): hmailserver, Exchange, Turbomail, etc.
    • Incoming mail server (mail Transfer Agent, MTA)
    • Incoming mail client (mail User Agent, MUA)


The SMTP protocol is used between the client and the server and the server during the sending process, and the POP3 or IMAP (POP3 substitution protocol, which supports message digest display and offline operation) is used between the client and the service side during the receive process. e-Mail can be simply considered a file transfer, but unlike FTP real-time file transfers, each mail server saves the mail file itself until it is received by the next mail server or client, similar to the difference between asynchronous and synchronous.



From the above, in order to successfully send and receive mail, the client setup or coding needs to strictly adapt to the requirements of the mail server. For sending messages need to be clear: SMTP server address and port (default port 25), whether to use secure connection (SSL), authentication credentials (user and password), and more detailed message format, message encoding method, etc. For receiving messages: POP3 or IMAP server address and port (POP3 default port 110,imap default port 143), whether to use secure connection (SSL), authentication credentials (user and password)






Ii. sending mail components and testing under C #



The components for sending mail under C # are more commonly used with the following three: System.Net.Mail, OPENSMTP, lumisoft.net. Let's test them separately.



Sending a message requires at least sending mail server information and message information, so we set up host and mail two configuration classes.


  public class ConfigHost
    {
        public string Server { get; set; }
        public int Port { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }
        public bool EnableSsl { get; set; }
    }

    public class ConfigMail
    {
        public string From { get; set; }
        public string[] To { get; set; }
        public string Subject { get; set; }
        public string Body { get; set; }
        public string[] Attachments { get; set; }
        public string[] Resources { get; set; }
    }

A unified interface Isendmail is also defined to facilitate testing and comparison.


  public interface ISendMail
    {
        void CreateHost(ConfigHost host);
        void CreateMail(ConfigMail mail);
        void CreateMultiMail(ConfigMail mail);
        void SendMail();
    }

1. Using System.Net.Mail



System.Net.Mail belongs to part of the. Net Framework. Net2.0 can use this component later.


 using System.Net.Mail;
    public class UseNetMail : ISendMail
    {
        private MailMessage Mail { get; set; }
        private SmtpClient Host { get; set; }

        public void CreateHost(ConfigHost host)
        {
            Host = new SmtpClient(host.Server, host.Port);
            Host.Credentials = new System.Net.NetworkCredential(host.Username, host.Password);
            Host.EnableSsl = host.EnableSsl;
        }

        public void CreateMail(ConfigMail mail)
        {
            Mail = new MailMessage();
            Mail.From = new MailAddress(mail.From);

            foreach (var t in mail.To)
                Mail.To.Add(t);

            Mail.Subject = mail.Subject;
            Mail.Body = mail.Body;
            Mail.IsBodyHtml = true;
            Mail.BodyEncoding = System.Text.Encoding.UTF8;
        }

        public void CreateMultiMail(ConfigMail mail)
        {
            CreateMail(mail);

            Mail.AlternateViews.Add(AlternateView.CreateAlternateViewFromString("If you see this message, it means that your mail client does not support html.", Encoding.UTF8, "text/plain"));

            var html = AlternateView.CreateAlternateViewFromString(mail.Body, Encoding.UTF8, "text/html");
            foreach (string resource in mail.Resources)
            {
                var image = new LinkedResource(resource, "image/jpeg");
                image.ContentId = Convert.ToBase64String(Encoding.Default.GetBytes(Path.GetFileName(resource)));
                html.LinkedResources.Add(image);
            }
            Mail.AlternateViews.Add(html);

            foreach (var attachment in mail.Attachments)
            {
                Mail.Attachments.Add(new Attachment(attachment));
            }
        }

        public void SendMail()
        {
            if (Host != null && Mail != null)
                Host.Send(Mail);
            else
                throw new Exception("These is not a host to send mail or there is not a mail need to be sent.");
        }
    }
2. Using OPENSMTPOpen source Send mail component, you can get the source code here. However, OPENSMTP does not currently support SSL.
 using OpenSmtp.Mail;
    public class UseOpenSmtp : ISendMail
    {
        private MailMessage Mail { get; set; }
        private Smtp Host { get; set; }

        public void CreateHost(ConfigHost host)
        {
            Host = new Smtp(host.Server, host.Username, host.Password, host.Port);
        }

        public void CreateMail(ConfigMail mail)
        {
            Mail = new MailMessage();
            Mail.From = new EmailAddress(mail.From);
            foreach (var t in mail.To)
                Mail.AddRecipient(t, AddressType.To);
            
            Mail.HtmlBody = mail.Body;
            Mail.Subject = mail.Subject;
            Mail.Charset = "UTF-8";
        }

        public void CreateMultiMail(ConfigMail mail)
        {
            CreateMail(mail);
            foreach (var attachment in mail.Attachments)
            {
                Mail.AddAttachment(attachment);
            }
            foreach (var resource in mail.Resources)
            {
                Mail.AddImage(resource, Convert.ToBase64String(Encoding.Default.GetBytes(Path.GetFileName(resource))));            
            }
        }

        public void SendMail()
        {
            if (Host != null && Mail != null)
                Host.SendMail(Mail);
            else
                throw new Exception("These is not a host to send mail or there is not a mail need to be sent.");
        }

3. Using Lumisoft.net



Lumisoft.net is a very powerful open source component that not only sends mail, but also can be used to receive mail, which is considered the best open source component. Here you can learn more about the namespace of the Lumisoft.net component, or download its source code and sample here.


using LumiSoft.Net.SMTP.Client;
    using LumiSoft.Net.AUTH;
    using LumiSoft.Net.Mail;
    using LumiSoft.Net.MIME;
    public class UseLumiSoft: ISendMail
    {
        private SMTP_Client Host {get; set;}
        private Mail_Message Mail {get; set;}

        public void CreateHost (ConfigHost host)
        {
            Host = new SMTP_Client ();
            Host.Connect (host.Server, host.Port, host.EnableSsl);
            Host.EhloHelo (host.Server);
            Host.Auth (Host.AuthGetStrongestMethod (host.Username, host.Password));
        }

        public void CreateMail (ConfigMail mail)
        {
            Mail = new Mail_Message ();
            Mail.Subject = mail.Subject;
            Mail.From = new Mail_t_MailboxList ();
            Mail.From.Add (new Mail_t_Mailbox (mail.From, mail.From));
            Mail.To = new Mail_t_AddressList ();
            foreach (var to in mail.To)
            {
                Mail.To.Add (new Mail_t_Mailbox (to, to));
            }
            var body = new MIME_b_Text (MIME_MediaTypes.Text.html);
            Mail.Body = body; // Need to be assigned first or will throw "Body must be bounded to some entity first" exception.
            body.SetText (MIME_TransferEncodings.Base64, Encoding.UTF8, mail.Body);
        }

        public void CreateMultiMail (ConfigMail mail)
        {
            CreateMail (mail);

            var contentTypeMixed = new MIME_h_ContentType (MIME_MediaTypes.Multipart.mixed);
            contentTypeMixed.Param_Boundary = Guid.NewGuid (). ToString (). Replace ("-", "_");
            var multipartMixed = new MIME_b_MultipartMixed (contentTypeMixed);
            Mail.Body = multipartMixed;

            // Create a entity to hold multipart / alternative body
            var entityAlternative = new MIME_Entity ();
            var contentTypeAlternative = new MIME_h_ContentType (MIME_MediaTypes.Multipart.alternative);
            contentTypeAlternative.Param_Boundary = Guid.NewGuid (). ToString (). Replace ("-", "_");
            var multipartAlternative = new MIME_b_MultipartAlternative (contentTypeAlternative);
            entityAlternative.Body = multipartAlternative;
            multipartMixed.BodyParts.Add (entityAlternative);

            var entityTextPlain = new MIME_Entity ();
            var plain = new MIME_b_Text (MIME_MediaTypes.Text.plain);
            entityTextPlain.Body = plain;
            plain.SetText (MIME_TransferEncodings.Base64, Encoding.UTF8, "If you see this message, it means that your mail client does not support html.");
            multipartAlternative.BodyParts.Add (entityTextPlain);

            var entityTextHtml = new MIME_Entity ();
            var html = new MIME_b_Text (MIME_MediaTypes.Text.html);
            entityTextHtml.Body = html;
            html.SetText (MIME_TransferEncodings.Base64, Encoding.UTF8, mail.Body);
            multipartAlternative.BodyParts.Add (entityTextHtml);

            foreach (string attachment in mail.Attachments)
            {
                multipartMixed.BodyParts.Add (Mail_Message.CreateAttachment (attachment));
            }

            foreach (string resource in mail.Resources)
            {
                var entity = new MIME_Entity ();
                entity.ContentDisposition = new MIME_h_ContentDisposition (MIME_DispositionTypes.Inline);
                entity.ContentID = Convert.ToBase64String (Encoding.Default.GetBytes (Path.GetFileName (resource))); //eg.<img src = "cid: ContentID" />
                var image = new MIME_b_Image (MIME_MediaTypes.Image.jpeg);
                entity.Body = image;
                image.SetDataFromFile (resource, MIME_TransferEncodings.Base64);
                multipartMixed.BodyParts.Add (entity);
            }
        }

        public void SendMail ()
        {
            if (Host! = null && Mail! = null)
            {
                foreach (Mail_t_Mailbox from in Mail.From.ToArray ())
                {
                    Host.MailFrom (from.Address, -1);
                }
                foreach (Mail_t_Mailbox to in Mail.To)
                {
                    Host.RcptTo (to.Address);
                }
                using (var stream = new MemoryStream ())
                {
                    Mail.ToStream (stream, new MIME_Encoding_EncodedWord (MIME_EncodedWordEncoding.Q, Encoding.UTF8), Encoding.UTF8);
                    stream.Position = 0; // Need to be reset to 0, otherwise nothing will be sent;
                    Host.SendMessage (stream);
                    Host.Disconnect ();
                }
            }
            else
                throw new Exception ("These is not a host to send mail or there is not a mail need to be sent.");
        }
    } 

Reading the source code of Lumisoft.net, you can see that lumisoft.net programming strictly follows the protocol specification defined by the RFC (Request for Comments). Reading the source code is also helpful for understanding the RFC and the specification of the Mail network protocol. This link is available if you want to review the RFC documentation.



In the code above, the Mime_mediatypes class, mime_ The Transferencodings class and the Encoding Class (System.Text.Encoding) are or are similar to enumerations that set the encoding or parsing of message content, which fundamentally determines the normal transmission and display of messages. The Mime_transferencodings class sets the file transfer encoding, which determines the value of the Content-transfer-encoding field in the message header and other encoding methods (such as multiple languages in the header) that require the transfer of the encoded field. The Mime_mediatypes class sets the type of content for each part of the message and determines the value of the Content-type field in the message. The encoding class, needless to say, determines the value of CharSet. The specific role of these settings will also be mentioned below, which is skipped here.






4. Testing



The following table is the configuration of the large SMTP servers that are collected over the network, and you can choose to test them with these configurations:


Service SMTP address SMTP port Enablessl
Gmail Smtp.google.com 465 or 587 True
126 Smtp.126.com 25 False
163 Smtp.126.com 25 False
Hotmail Smtp.live.com 25 True
Sina Smtp.sina.com 25 False
Sohu Smtp.sohu.com 25 False


Create a new console application to test sending simple messages that contain only the body:


    Class program    {        static void Main (string[] args)        {           var h1 = new Confighost ()            {                Server = " Smtp.gmail.com ",                Port = 465,                Username =" ****** @gmail. com ",                Password =" ****** ",                Enablessl = true< c13/>};
 class Program
    {
        static void Main(string[] args)
        {           var h1 = new ConfigHost()
            {
                Server = "smtp.gmail.com",
                Port = 465,
                Username = "******@gmail.com",
                Password = "******",
                EnableSsl = true
            };
var m1 = new ConfigMail()
            {
                Subject = "Test",
                Body = "Just a test.",
                From = "******@gmail.com",
                To = new string[] { "******@gmail.com" }, 
            };

            var agents = new List<ISendMail>() { new UseNetMail(), new UseOpenSmtp(), new UseLumiSoft() };
            foreach (var agent in agents)
            {
                var output = "Send m1 via h1 " + agent.GetType().Name + " ";
                Console.WriteLine(output + "start");
                try
                {
                    agent.CreateHost(h1);
                    m1.Subject = output;        
                    agent.CreateMail(m1);
                    agent.SendMail();
                    Console.WriteLine(output + "success");
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                Console.WriteLine(output + "end");
                Console.WriteLine("-----------------------------------");
            }
            Console.Read();
        }
    }

When sending mail via Gmail, OPENSMTP failed to support SSL send, Netmail use port 587 to successfully send, Lumisoft use 465 port can successfully send. Check out the Gmail documentation that says Gmail's 465 port uses the SSL protocol, while 587 ports use the TLS protocol, but 587 requires STARTTLS command support to be promoted to TLS. Testing the discovery at the command prompt does not require the TLS protocol to be used until the STARTTLS command is sent:

> telnet smtp.gmail.com 587
220 mx.google.com ESMTP o5sm40420786eeg.8 - gsmtp
EHLO g1
250-mx.google.com at your service, [173.231.8.212]
250-SIZE 35882577
250-8BITMIME
250-STARTTLS
250-ENHANCEDSTATUSCODES
250 CHUNKING
AUTH LOGIN
530 5.7.0 Must issue a STARTTLS command first. o5sm40420786eeg.8 – gsmtpSTARTTLS220 
STARTTLS
2.0.0 Ready to start TLS
QUIT

For TLS and STARTTLS people often get confused, here's an explanation of them, click here.



Thus lumisoft if you need to explicitly send the StartTLS command when you connect to the Gmail server, you have found that Lumisoft has a method Smtp_client.starttls (), and it is more complicated to connect to Gmail than the other SMTP servers. Other servers require that the username in the mail configuration be consistent with the From and require special attention.






To test sending messages with attachments and inline resources:


    Class program    {        static void Main (string[] args)        {            var h2 = new Confighost ()            {                Server = "smtp.163 . com ",                Port = +,                Username =" ******@163.com ",                Password =" ****** ",                Enablessl = False            };            var m2 = new Configmail ()            {                Subject = "Test",
 class Program
    {
        static void Main(string[] args)
        {
            var h2 = new ConfigHost()
            {
                Server = "smtp.163.com",
                Port = 25,
                Username = "******@163.com",
                Password = "******",
                EnableSsl = false
            };
            var m2 = new ConfigMail()
            {
                Subject = "Test",
                Body = "Just a test. <br/><img src=‘cid:" + Convert.ToBase64String(Encoding.Default.GetBytes("Resource.jpg")) + "‘ alt=‘‘/> ", 
                From = "******@163.com",
                To = new string[] { "******@163.com" }, 
                Attachments = new string[] { @"E:\Test\SendMail\Attachment.pdf" }, 
                Resources = new string[] { @"E:\Test\SendMail\Resource.jpg" } 
            };
          var agents = new List<ISendMail>() { new UseNetMail(), new UseOpenSmtp(), new UseLumiSoft() };
            foreach (var agent in agents)
            {
                var output = "Send m2 via h2 " + agent.GetType().Name + " ";
                Console.WriteLine(output + "start");
                try
                {
                    agent.CreateHost(h2);
                    m2.Subject = output;        
                    agent.CreateMultiMail(m2);
                    agent.SendMail();
                    Console.WriteLine(output + "success");
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                Console.WriteLine(output + "end");
                Console.WriteLine("-----------------------------------");
            }
            Console.Read();
        }
    }

C # Mail sending problem (i)


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.