Stream实现基于SMTP协议的邮件发送(C#实现)

发布于 2013-11-23  34.9k 次阅读


T1:

这里采用的是SMTP的命令格式,不明白的请参考度娘:http://baike.baidu.com/link?url=hbb2lcP0BZK4bDQn964p4_d4O4odwLJQcPs2pHscR_kyt8vIRhlPmbUBJP5hpo_Q#2_1

Stream字节流的基本读写代码我不累赘说明了,看邮件所传输的内容:

=======================================

Received: from m12-15.163.com (unknown [220.181.12.15])
by newmx82.qq.com (NewMx) with SMTP
id ; Sat, 23 Nov 2013 16:24:35 +0800
X-QQ-SSF: 013000000A000020016000010100621
X-QQ-mid: mx82t1385195075tyilr4nm7
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=163.com;
s=s110527; h=DKIM-Signature:Received:Message-ID:From:To:Cc:Date:
Subject:MIME-Version:Content-Type:Content-Transfer-Encoding;
bh=/5/HxwsvXODjAfDROaNbyiz/omLSVmLLSjsYzpOvFVc=; b=Y5XljdF7+ePXX
lpKxGIQwVO7MlNMS/RN/+yOSLf2GcxPDJiKwrUhehfpDdnYdm4zu2NecAVkRRCIw
Pm1xVMUdUnG5JtEEfdTOHX8jNcF85kkfcT567rnnqkhkq9Cya0OLGI66owiGMTLY
yIOy0oGqk+iOm1aEwb/ZFggbs3bls8=
Received: from 163.com (unknown [113.91.231.14])
by smtp11 (Coremail) with SMTP id D8CowEB5nVVBZpBSFFk3AA--.1599S2;
Sat, 23 Nov 2013 16:24:34 +0800 (CST)
X-Coremail-DSSMTP: 113.91.231.14
Message-ID: <20131123162430-A88626D2E385@163.com>
Return-path: <jingtingzhiwu@163.com>
From: =?utf-8?B?d2lsa2V5?= <jingtingzhiwu@163.com>
To: =?utf-8?B?cXE=?= <411626730@qq.com>
Cc: =?utf-8?B?NjY0MTk4NEBxcS5jb20=?= <6641984@qq.com>
Date: 六, 23 十一月 2013 16:24:30 +08
Subject: =?utf-8?B?dHR0?=
X-Priority: 3
X-Mailer: Netease.Net
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: base64
X-CM-TRANSID:D8CowEB5nVVBZpBSFFk3AA--.1599S2
X-Coremail-Antispam: 1Uf129KBjDUn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7v73
VFW2AGmfu7bjvjm3AaLaJ3UbIYCTnIWIevJa73UjIFyTuYvjxUswvKUUUUU
X-CM-SenderInfo: pmlqw3hlqj6xxlzxqiywtou0bp/1tbitAPebFD+Ow5bYgAAsn

ZGRkZGE=

======================下划线的地方需要手动设置头信息==================

有一点要注意,抄送(CC)和暗送(BCC)都是通过RCPT TO 命令实现,RCPT TO 可以跟多个邮件接收人地址,但是每个接收人需要Stream流单独一个指令

// Account 1
Stream.Write(Encoding.Default.GetBytes("RCPT TO : <admin@wilkey.me>"), 0, 8192);
                        
// Account 2 
Stream.Write(Encoding.Default.GetBytes("RCPT TO : <sir@wilkey.me>"), 0, 8192);

然后要设置SMTP的头信息:

mHeader.Append("Message-ID: " + mid + this.CRLF);
            mHeader.Append("Return-path: <" + Message.FromAddr + ">" + this.CRLF);
            mHeader.Append("From: =?utf-8?B?" + Message.FromName.Base64Encode() + "?= <" + Message.FromAddr + ">" + this.CRLF);
            mHeader.Append("To: =?utf-8?B?" + Message.Recipient.Name.Base64Encode() + "?= <" + Message.Recipient.Address + ">" + this.CRLF);
            if (!string.IsNullOrEmpty(Message.Recipient.Cc)) { mHeader.Append("Cc: =?utf-8?B?" + Message.Recipient.Cc.Base64Encode() + "?= <" + Message.Recipient.Cc + ">" + this.CRLF); }
         //   mail.Append("Reply-To: "" + Message.FromName + "" <" + Message.FromAddr + ">" + this.CRLF);
            mHeader.Append("Date: " + DateTime.Now.ToString("ddd, dd MMM yyyy HH:mm:ss zz") + this.CRLF);
            mHeader.Append("Subject: =?utf-8?B?" + Message.Subject.Base64Encode() + "?=" + this.CRLF);
            mHeader.Append("X-Priority: 3" + this.CRLF);
            mHeader.Append("X-Mailer: " + MailAgent + this.CRLF);
            mHeader.Append("MIME-Version: 1.0" + this.CRLF);        
                                            
            StringBuilder attatchments = new StringBuilder();
                      
            // has attachment
            if (Message.Attachments.Count > 0)
            {
                mHeader.Append("Content-Type: multipart/mixed;" + this.CRLF);
                mHeader.Append(" ".PadRight(8, ' ') + "boundary="" + m_bound + """ + this.CRLF);
                mHeader.Append(this.CRLF);
                      
                mHeader.Append("--" + m_bound + this.CRLF);                
                                     
                foreach (string file in Message.Attachments)
                {                     
                    if (File.Exists(file))
                    {
                        attatchments.Append("--" + m_bound + this.CRLF);
                        attatchments.Append("Content-Type:" + MIME.GetType(file) + this.CRLF);
                        attatchments.Append("Content-Transfer-Encoding: base64" + this.CRLF);
                        attatchments.Append("Content-Disposition: attachment; filename="" + Path.GetFileName(file) + """ + this.CRLF + this.CRLF);
                        attatchments.Append(this.getFileBytes(file).Base64Encode().ChunkSplit(this.bodyWidth));       
                        attatchments.Append(this.CRLF);
                    }
                }
            }

BCC是不需要写入头信息哦。

T2:

另外还有一种方法直接用SMTP包,非常简单,JAVA可以用jmail

Smtp mailer = new Smtp();
             
// Use SMTP relay with authentication.
mailer.SmtpServers.Add("mail.provider.com", "jdoe@here.com", "secret");
             
// Set From address (will also use it as real sender's address).
mailer.Message.From.AsString = "John Doe <jdoe@here.com>";
             
// Set "To" but do not list any actual recipients there.
mailer.Message.To.AsString = "undisclosed recipients";
             
// Set other fields.
mailer.Message.Subject = "Notification";
mailer.Message.BodyPlainText = "Meet at midnight";
             
// Create the actual list of recipients.
EmailAddressCollection emails = new EmailAddressCollection();
emails.Add("mr.x@somewhere.com");
emails.Add("mrs.y@nowhere.com");
emails.Add("mr.z@elsewhere.com");
             
// Send to real recipients. We could also use comma-separated string
// of e-mail addresses rather than EmailAddressCollection object.
mailer.Send(null, emails);