⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pop3mimeclient.cs

📁 《征服Ajax》原书的例题源码
💻 CS
📖 第 1 页 / 共 2 页
字号:
          case "content-disposition":
            message.ContentDisposition = new ContentDisposition(headerLineContent);
            break;
          case "content-id":
            message.ContentId = headerLineContent;
            break;
          case "content-transfer-encoding":
            message.TransferType = headerLineContent;
            message.ContentTransferEncoding = ConvertToTransferEncoding(headerLineContent);
            break;
          case "content-type":
            message.SetContentTypeFields(headerLineContent);
            break;
          case "date":
            message.DeliveryDate = ConvertToDateTime(headerLineContent);
            break;
          case "delivered-to":
            message.DeliveredTo = ConvertToMailAddress(headerLineContent);
            break;
          case "from":
            MailAddress address = ConvertToMailAddress(headerLineContent);
            if (address!=null) {
              message.From = address;
            }
            break;
          case "message-id":
            message.MessageId = headerLineContent;
            break;
          case "mime-version":
            message.MimeVersion = headerLineContent;
            //message.BodyEncoding = new Encoding();
            break;
          case "sender":
            message.Sender = ConvertToMailAddress(headerLineContent);
            break;
          case "subject":
            message.Subject = headerLineContent;
            break;
          case "received":
            //throw mail routing information away
            break;
          case "reply-to":
            message.ReplyTo = ConvertToMailAddress(headerLineContent);
            break;
          case "return-path":
            message.ReturnPath = ConvertToMailAddress(headerLineContent);
            break;
          case "to":
            AddMailAddresses(headerLineContent, message.To);
            break;
          default:
            message.UnknowHeaderlines.Add(headerField);
            if (isCollectUnknowHeaderLines) {
              AllUnknowHeaderLines.Add(headerField);
            }
            break;
        }
      }
    }
    

    /// <summary>
    /// find individual addresses in the string and add it to address collection
    /// </summary>
    /// <param name="Addresses">string with possibly several email addresses</param>
    /// <param name="AddressCollection">parsed addresses</param>
    private void AddMailAddresses(string Addresses, MailAddressCollection AddressCollection) {
      MailAddress adr;
      try {
        string[] AddressSplit = Addresses.Split(',');
        foreach (string adrString in AddressSplit) {
          adr = ConvertToMailAddress(adrString);
          if (adr!=null) {
            AddressCollection.Add(adr);
          }
        }
      } catch {
        System.Diagnostics.Debugger.Break(); //didn't have a sample email to test this
      }
    }


    /// <summary>
    /// Tries to convert a string into an email address
    /// </summary>
    public MailAddress ConvertToMailAddress(string address) {
      address = address.Trim();
      if (address=="<>") {
        //empty email address, not recognised a such by .NET
        return null;
      }
      try {
        return new MailAddress(address);
      } catch {
        callGetEmailWarning("address format not recognised: '" + address.Trim() + "'");
      }
      return null;
    }


    private IFormatProvider culture = new CultureInfo("en-US", true);

    /// <summary>
    /// Tries to convert string to date, following POP3 rules
    /// If there is a run time error, the smallest possible date is returned
    /// <example>Wed, 04 Jan 2006 07:58:08 -0800</example>
    /// </summary>
    public DateTime ConvertToDateTime(string date) {
      DateTime ReturnDateTime;
      try {
        //sample; 'Wed, 04 Jan 2006 07:58:08 -0800 (PST)'
        //remove day of the week before ','
        //remove date zone in '()', -800 indicates the zone already

        //remove day of week
        string cleanDateTime = date;
        string[] DateSplit = cleanDateTime.Split(CommaChars, 2);
        if (DateSplit.Length>1) {
          cleanDateTime = DateSplit[1];
        }

        //remove time zone (PST)
        DateSplit = cleanDateTime.Split(BracketChars);
        if (DateSplit.Length>1) {
          cleanDateTime = DateSplit[0];
        }

        //convert to DateTime
        if (!DateTime.TryParse(
          cleanDateTime,
          culture,
          DateTimeStyles.AdjustToUniversal|DateTimeStyles.AllowWhiteSpaces,
          out ReturnDateTime)) {
          //try just to convert the date
          int DateLength = cleanDateTime.IndexOf(':') - 3;
          cleanDateTime = cleanDateTime.Substring(0, DateLength);

          if (DateTime.TryParse(
            cleanDateTime,
            culture,
            DateTimeStyles.AdjustToUniversal|DateTimeStyles.AllowWhiteSpaces,
            out ReturnDateTime)) {
            callGetEmailWarning("got only date, time format not recognised: '" + date + "'");
          } else {
            callGetEmailWarning("date format not recognised: '" + date + "'");
            System.Diagnostics.Debugger.Break();  //didn't have a sample email to test this
            return DateTime.MinValue;
          }
        }

      } catch {
        callGetEmailWarning("date format not recognised: '" + date + "'");
        return DateTime.MinValue;
      }
    return ReturnDateTime;
    }


    /// <summary>
    /// converts TransferEncoding as defined in the RFC into a .NET TransferEncoding
    /// 
    /// .NET doesn't know the type "bit8". It is translated here into "bit7", which
    /// requires the same kind of processing (none).
    /// </summary>
    /// <param name="TransferEncodingString"></param>
    /// <returns></returns>
    private TransferEncoding ConvertToTransferEncoding(string TransferEncodingString) {
      // here, "bit8" is marked as "bit7" (i.e. no transfer encoding needed)
      // "binary" is illegal in SMTP
      // something like "7bit" / "8bit" / "binary" / "quoted-printable" / "base64"
      switch (TransferEncodingString.Trim().ToLowerInvariant()) {
        case "7bit":
        case "8bit":
          return TransferEncoding.SevenBit;
        case "quoted-printable":
          return TransferEncoding.QuotedPrintable;
        case "base64":
          return TransferEncoding.Base64;
        case "binary":
          throw new Pop3Exception("SMPT does not support binary transfer encoding");
        default:
          callGetEmailWarning("not supported content-transfer-encoding: " + TransferEncodingString);
          return TransferEncoding.Unknown;
      }
    }


    /// <summary>
    /// Copies the content found for the MIME entity to the RxMailMessage body and creates
    /// a stream which can be used to create attachements, alternative views, ...
    /// </summary>
    private void saveMessageBody(RxMailMessage message, string contentString) {
      message.Body = contentString;
      MemoryStream bodyStream = new MemoryStream();
      StreamWriter bodyStreamWriter = new StreamWriter(bodyStream);
      bodyStreamWriter.Write(contentString);
      int l = contentString.Length;
      bodyStreamWriter.Flush();
      message.ContentStream = bodyStream;
    }


    /// <summary>
    /// each attachement is stored in its own MIME entity and read into this entity's
    /// ContentStream. SaveAttachment creates an attachment out of the ContentStream
    /// and attaches it to the parent MIME entity.
    /// </summary>
    private void SaveAttachment(RxMailMessage message) {
      if (message.Parent==null) {
        System.Diagnostics.Debugger.Break(); //didn't have a sample email to test this
      } else {
        Attachment thisAttachment = new Attachment(message.ContentStream, message.ContentType);

        //no idea why ContentDisposition is read only. on the other hand, it is anyway redundant
        if (message.ContentDisposition!=null) {
          ContentDisposition messageContentDisposition = message.ContentDisposition;
          ContentDisposition AttachmentContentDisposition = thisAttachment.ContentDisposition;
          if (messageContentDisposition.CreationDate>DateTime.MinValue) {
            AttachmentContentDisposition.CreationDate = messageContentDisposition.CreationDate;
          }
          AttachmentContentDisposition.DispositionType = messageContentDisposition.DispositionType;
          AttachmentContentDisposition.FileName = messageContentDisposition.FileName;
          AttachmentContentDisposition.Inline = messageContentDisposition.Inline;
          if (messageContentDisposition.ModificationDate>DateTime.MinValue) {
            AttachmentContentDisposition.ModificationDate = messageContentDisposition.ModificationDate;
          }
          AttachmentContentDisposition.Parameters.Clear();
          if (messageContentDisposition.ReadDate>DateTime.MinValue) {
            AttachmentContentDisposition.ReadDate = messageContentDisposition.ReadDate;
          }
          if (messageContentDisposition.Size>0) {
            AttachmentContentDisposition.Size = messageContentDisposition.Size;
          }
          foreach (string key in messageContentDisposition.Parameters.Keys) {
            AttachmentContentDisposition.Parameters.Add(key, messageContentDisposition.Parameters[key]);
          }
        }

        //get ContentId
        string contentIdString = message.ContentId;
        if (contentIdString!=null) {
          thisAttachment.ContentId = RemoveBrackets(contentIdString);
        }
        thisAttachment.TransferEncoding = message.ContentTransferEncoding;
        message.Parent.Attachments.Add(thisAttachment);
      }
    }



    /// <summary>
    /// removes leading '&lt;' and trailing '&gt;' if both exist
    /// </summary>
    /// <param name="parameterString"></param>
    /// <returns></returns>
    private string RemoveBrackets(string parameterString) {
      if (parameterString==null) {
        return null;
      }
      if (parameterString.Length<1 ||
            parameterString[0]!='<' || 
            parameterString[parameterString.Length-1]!='>') {
        System.Diagnostics.Debugger.Break(); //didn't have a sample email to test this
        return parameterString;
      } else {
        return parameterString.Substring(1, parameterString.Length-2);
      }
    }


    private MimeEntityReturnCode ProcessDelimitedBody(
      RxMailMessage message, 
      string BoundaryStart,
      string parentBoundaryStart, 
      string parentBoundaryEnd) 
    {
      string response;

      if (BoundaryStart.Trim()==parentBoundaryStart.Trim()) {
        //Mime entity boundaries have to be unique
        callGetEmailWarning("new boundary same as parent boundary: '{0}'", parentBoundaryStart);
        //empty this message
        while (readMultiLine(out response)) { }
        return MimeEntityReturnCode.problem;
      }

      //
      MimeEntityReturnCode ReturnCode;
      do {
        
        //empty StringBuilder
        MimeEntitySB.Length=0;
        RxMailMessage ChildPart = message.CreateChildEntity();

        //recursively call MIME part processing
        ReturnCode = ProcessMimeEntity(ChildPart, BoundaryStart);

        if (ReturnCode==MimeEntityReturnCode.problem) {
          //it seems the received email doesn't follow the MIME specification. Stop here
          return MimeEntityReturnCode.problem;
        }
        
        //add the newly found child MIME part to the parent
        AddChildPartsToParent(ChildPart, message);
      } while (ReturnCode!= MimeEntityReturnCode.parentBoundaryEndFound);

      //disregard all future lines until parent boundary is found or end of complete message
      MimeEntityReturnCode boundaryMimeReturnCode;
      bool hasParentBoundary = parentBoundaryStart.Length>0;
      while (readMultiLine(out response)) {
        if (hasParentBoundary && parentBoundaryFound(response, parentBoundaryStart, parentBoundaryEnd, out boundaryMimeReturnCode)) {
          return boundaryMimeReturnCode;
        }
      }

      return MimeEntityReturnCode.bodyComplete;
    }


    /// <summary>
    /// Add all attachments and alternative views from child to the parent
    /// </summary>
    private void AddChildPartsToParent(RxMailMessage child, RxMailMessage parent) {
      //add the child itself to the parent
      parent.Entities.Add(child);

      //add the alternative views of the child to the parent
      if (child.AlternateViews!=null) {
        foreach (AlternateView childView in child.AlternateViews) {
          parent.AlternateViews.Add(childView);
        }
      }

      //add the body of the child as alternative view to parent
      //this should be the last view attached here, because the POP 3 MIME client
      //is supposed to display the last alternative view
      if (child.MediaMainType=="text" && child.ContentStream!=null) {
        AlternateView thisAlternateView = new AlternateView(child.ContentStream);
        thisAlternateView.ContentId = RemoveBrackets(child.ContentId);
        thisAlternateView.ContentType = child.ContentType;
        thisAlternateView.TransferEncoding = child.ContentTransferEncoding;
        parent.AlternateViews.Add(thisAlternateView);
      }

      //add the attachments of the child to the parent
      if (child.Attachments!=null) {
        foreach (Attachment childAttachment in child.Attachments) {
          parent.Attachments.Add(childAttachment);
        }
      }
    }


    /// <summary>
    /// Converts byte array to string, using decoding as requested
    /// </summary>
    public string DecodeByteArryToString(byte[] ByteArry, Encoding ByteEncoding) {
      if (ByteArry==null) {
        //no bytes to convert
        return null;
      }
      Decoder byteArryDecoder;
      if (ByteEncoding==null){
        //no encoding indicated. Let's try UTF7
        System.Diagnostics.Debugger.Break(); //didn't have a sample email to test this
        byteArryDecoder = Encoding.UTF7.GetDecoder();
      }else{
        byteArryDecoder = ByteEncoding.GetDecoder();
      }
      int charCount = byteArryDecoder.GetCharCount(ByteArry, 0, ByteArry.Length);
      char[] bodyChars = new Char[charCount];
      int charsDecodedCount = byteArryDecoder.GetChars(ByteArry, 0, ByteArry.Length, bodyChars, 0);
      //convert char[] to string
      return new string(bodyChars);
    }


  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -