Beispiel #1
0
        /// <summary>
        /// 初始化邮件体
        /// </summary>
        public MailMessage()
        {
            var now = DateTime.Now;

            this.messageId = MailCommon.BuildMessageID(now);
            //this.boundary = MailCommon.BuildBoundary(now);
            this.boundary = this.messageId;
        }
Beispiel #2
0
        /// <summary>
        /// 创建用于邮件体的邮件地址集合的数组
        /// </summary>
        /// <param name="addressList">须要处理的集合</param>
        /// <param name="encoding"></param>
        /// <returns>返回字符串型式数组</returns>
        public static string JoinAddressList(List <MailAddress> addressList, Encoding encoding)
        {
            var array = new string[addressList.Count];

            for (int i = 0, l = addressList.Count; i < l; i++)
            {
                var address = addressList[i];
                array[i] = MailCommon.Base64EncodeAddress(address.Name, address.Address, encoding);
            }

            var result = string.Join(",", array);

            return(result);
        }
Beispiel #3
0
        ///// <summary>
        ///// 将一个数组合并成符合邮件的每行最大76字符字符串,结果追加至字符构建对象
        ///// </summary>
        ///// <param name="list"></param>
        ///// <param name="builder"></param>
        ///// <param name="lineStart">每行初始字符</param>
        //public static void JoinLine76Break(StringBuilder builder, IList<string> list, string lineStart)
        //{
        //    var lineLength = builder.Length;
        //    var lineStartLength = lineStart.Length;

        //    if (lineStartLength > 76)
        //    {
        //        throw new ArgumentOutOfRangeException("lineStart", "length limit less than 76.");
        //    }

        //    for (int i = 0, l = list.Count; i < l; i++)
        //    {
        //        var itemLength = list[i].Length;
        //        if (lineLength + itemLength > 76)
        //        {
        //            builder.Append(MailCommon.NewLine);
        //            builder.Append(lineStart);

        //            lineLength = itemLength + lineStartLength;
        //        }
        //        else
        //        {
        //            lineLength += itemLength;
        //        }
        //        builder.Append(list[i]);
        //    }
        //}

        /// <summary>
        /// 编码邮件地址头
        /// </summary>
        /// <param name="name"></param>
        /// <param name="address"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        public static string Base64EncodeAddress(string name, string address, Encoding encoding)
        {
            //判断姓名是否为空
            if (string.IsNullOrEmpty(name))
            {
                name = address.Split('@')[0];
            }

            //判断姓名是否为键盘可打印,如果是,则不进行编码,如果不是,则进行编码
            if (MailCommon.IsAscii(name) == false)
            {
                name = MailCommon.Base64EncodHead(name, encoding);
            }

            return("\"" + name + "\" <" + address + ">");
        }
Beispiel #4
0
        private string GenerateBody()
        {
            if (string.IsNullOrEmpty(this.Body))
            {
                throw new InvalidOperationException("message.Body is empty");
            }

            //编码完成
            var body = Convert.ToBase64String(this.encoding.GetBytes(this.Body));


            var sb = new StringBuilder();

            //begin
            sb.Append("--");
            sb.Append(this.boundary);
            sb.Append(MailCommon.NewLine);  //分隔完成

            if (this.IsBodyHtml == true)
            {
                sb.Append("Content-Type: text/html; charset=" + this.encoding.HeaderName);
            }
            else
            {
                sb.Append("Content-Type: text/plain; charset=" + this.encoding.HeaderName);
            }
            sb.Append(MailCommon.NewLine);
            sb.Append("Content-Transfer-Encoding: base64");
            sb.Append(MailCommon.NewLine);
            sb.Append(MailCommon.NewLine);
            sb.Append(MailCommon.Line76Break(body));
            sb.Append(MailCommon.NewLine);
            sb.Append(MailCommon.NewLine);

            //end
            // "--" + this.Boundary + "--" + MailCommon.NewLine;
            sb.Append("--");
            sb.Append(this.Boundary);
            sb.Append("--");
            sb.Append(MailCommon.NewLine);

            return(sb.ToString());
        }
Beispiel #5
0
        /// <summary>
        /// 获取邮件头,并填充 OutputHeaders
        /// </summary>
        /// <exception cref="InvalidOperationException">message.From invalid or message.To is empty or subject is empty</exception>
        /// <returns></returns>
        public string GetHead()
        {
            if (this.From == null || string.IsNullOrEmpty(this.From.Address))
            {
                throw new InvalidOperationException("message.From invalid");
            }

            if (this.To == null || this.To.Count == 0)
            {
                throw new InvalidOperationException("message.To is empty");
            }

            if (string.IsNullOrEmpty(this.Subject))
            {
                throw new InvalidOperationException("subject is empty");
            }

            this.outputHeaders = new NameValueCollection(15 + this.headers.Count);

            StringBuilder sb = new StringBuilder();

            //message id
            var messageId = "<" + this.messageId + ">";

            sb.Append("Message-ID: ");
            sb.Append(messageId);
            sb.Append(MailCommon.NewLine);
            outputHeaders["Message-ID"] = messageId;

            //from
            var from = MailCommon.Base64EncodeAddress(this.From.Name, this.From.Address, this.encoding);

            sb.Append("From: ");
            sb.Append(from);
            sb.Append(MailCommon.NewLine);
            outputHeaders["From"] = from;

            //replay
            if (this.ReplyTo != null)
            {
                var replayTo = MailCommon.Base64EncodeAddress(this.ReplyTo.Name, this.ReplyTo.Address, this.encoding);
                sb.Append("Replay-To: ");
                sb.Append(replayTo);
                sb.Append(MailCommon.NewLine);
                outputHeaders["Replay-To"] = replayTo;
            }
            //to
            var to = MailCommon.JoinAddressList(this.to, this.encoding);

            sb.Append("To: ");
            sb.Append(to);
            sb.Append(MailCommon.NewLine);
            outputHeaders["To"] = to;
            //cc
            if (this.cc != null && this.cc.Count > 0)
            {
                var cc = MailCommon.JoinAddressList(this.cc, this.encoding);
                sb.Append("CC: ");
                sb.Append(cc);
                sb.Append(MailCommon.NewLine);
                outputHeaders["CC"] = cc;
            }
            //Subject
            var subject = "";

            sb.Append("Subject: ");
            if (MailCommon.IsAscii(this.Subject))
            {
                subject = this.Subject;
            }
            else
            {
                subject = MailCommon.Base64EncodHead(this.Subject, this.encoding);
            }
            sb.Append(subject);
            sb.Append(MailCommon.NewLine);
            outputHeaders["Subject"] = subject;

            //Data
            var date = DateTime.UtcNow.ToString("R");

            sb.Append("Date: ");
            sb.Append(date);
            sb.Append(MailCommon.NewLine);
            outputHeaders["Date"] = date;

            //Mime
            sb.Append(MailCommon.MimeVersion);
            sb.Append(MailCommon.NewLine);
            outputHeaders["MIME-Version"] = "1.0";

            //priority
            if (this.Priority != MailPriority.Normal)
            {
                sb.Append("X-Priority: ");
                sb.Append((int)this.Priority);
                sb.Append(MailCommon.NewLine);
                outputHeaders["X-Priority"] = ((int)this.Priority).ToString();
            }
            //Mailer
            sb.Append(MailCommon.Mailer);
            sb.Append(MailCommon.NewLine);
            outputHeaders["X-Mailer"] = "http://www.aooshi.org/adf/";

            //Content-Type
            //sb.Append(CreateContentType());
            var contentType = "multipart/alternative;\r\n\tboundary=\"" + this.boundary + "\"";

            sb.Append("Content-Type: ");
            sb.Append(contentType);
            sb.Append(MailCommon.NewLine);
            outputHeaders["Content-Type"] = contentType;

            //encoding
            sb.Append("Content-Transfer-Encoding: base64");
            sb.Append(MailCommon.NewLine);
            outputHeaders["Content-Transfer-Encoding"] = "base64";

            //custom headers
            foreach (var key in this.headers.AllKeys)
            {
                sb.Append(key);
                sb.Append(": ");
                sb.Append(this.headers[key]);
                sb.Append(MailCommon.NewLine);

                //
                outputHeaders[key] = this.headers[key];
            }

            //dkim
            var dkim = this.dkim;

            if (dkim != null)
            {
                var dkimValue = dkim.Sign(this);
                //
                sb.Insert(0, dkimValue + MailCommon.NewLine);
            }

            //
            sb.Append(MailCommon.NewLine);

            return(sb.ToString());
        }
Beispiel #6
0
        /// <summary>
        /// DKIM message
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public string Sign(MailMessage message)
        {
            //http://dkimcore.org/specification.html#1
            //DKIM-Signature: v=1;a=rsa-sha256;bh=BODYHASH;c=relaxed;d=TOKEN;h=HEADERS;s=SELECTOR;b=SIGNATURE

            //http://www.dkim.org/specs/rfc4871-dkimbase.html#dkim-sig-hdr

            /*
             * DKIM-Signature: v=1; a=rsa-sha256; c=simple/relaxed; d=domain.com;
             * h=From:To:Subject:Date; q=dns/txt; s=newsletter17100; t=1510020630;
             * bh=+5tUEqyyuolGsLc9usglUSkelpZtxEkEWKaGC21PSEM=;
             * b=
             */

            var dsLength = "DKIM-Signature: ".Length;

            var build = new StringBuilder(128);

            build.Append("DKIM-Signature:");
            build.Append(" v=1;");


            //
            string algorithm = this.algorithm == DKIMAlgorithm.RSASha1 ? "rsa-sha1" : "rsa-sha256";

            build.Append(" a=").Append(algorithm).Append(';');

            //c=header type / bodey type;
            string htype = this.headerType == DKIMType.Simple ? "simple" : "relaxed";
            string bType = this.bodyType == DKIMType.Simple ? "simple" : "relaxed";

            //build.Append(" c=simple/relaxed;");
            build.Append(" c=").Append(htype).Append('/').Append(bType).Append(';').Append(MailCommon.NewLine);
            //create time
            long unixtime = Adf.UnixTimestampHelper.ToInt64Timestamp();

            build.Append("\tt=").Append(unixtime).Append(';');
            build.Append(" q=dns/txt;").Append(MailCommon.NewLine);
            // domain
            build.Append("\td=").Append(domain).Append(';');
            // DNS selector
            build.Append(" s=").Append(selector).Append(';').Append(MailCommon.NewLine);

            //headers
            build.Append("\th=").Append(string.Join(":", this.signHeaders)).Append(';').Append(MailCommon.NewLine);

            //body hash
            var body = "";

            if (this.bodyType == DKIMType.Relaxed)
            {
                body = this.RelaxedBodyCanonicalization(message.GetBody());
            }
            else
            {
                body = this.SimpleBodyCanonicalization(message.GetBody());
            }

            var bodyBytes  = message.Encoding.GetBytes(body);
            var bodySigned = this.Hash(bodyBytes);
            var bodyHash   = Convert.ToBase64String(bodySigned);

            build.Append("\tbh=").Append(bodyHash).Append(';').Append(MailCommon.NewLine);
            //b
            build.Append("\tb=");

            //build string

            /*
             * DKIM-Signature: v=1; a=rsa-sha256; c=simple/relaxed; d=caping.co.id;
             * s=newsletter17800; q=dns/txt; t=1510023325; h=From:To:Subject:Date;
             * h=yklAmb1CNh0SAfmrk97PlZTEHrGKV94Ps6R7KDwLLoo=;
             * b=
             */

            //set current DKIM-Signature
            var dkimHead = build.ToString(dsLength, build.Length - dsLength);

            message.OutputHeaders["DKIM-Signature"] = dkimHead;

            var headers = "";

            if (this.headerType == DKIMType.Relaxed)
            {
                headers = this.RelaxedHeaderCanonicalization(message.OutputHeaders);
            }
            else
            {
                headers = this.SimpleHeaderCanonicalization(message.OutputHeaders);
            }
            var headerBytes  = message.Encoding.GetBytes(headers);
            var headerSigned = this.Sign(headerBytes);

            // assumes signature ends with "b="
            var b = Convert.ToBase64String(headerSigned);

            b = MailCommon.Line76Break("b=" + b, "\t");


            //remove last b
            build.Length -= "\tb=".Length;
            //append b
            build.Append(b);


            //update DKIM-Signature
            dkimHead = build.ToString(dsLength, build.Length - dsLength);
            message.OutputHeaders["DKIM-Signature"] = dkimHead;

            var signed = build.ToString();

            return(signed);
        }