/// <summary> /// Starts operation processing. /// </summary> /// <param name="owner">Owner POP3 client message.</param> /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns> /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception> internal bool Start(POP3_ClientMessage owner) { if(owner == null){ throw new ArgumentNullException("owner"); } m_pOwner = owner; m_pPop3Client = owner.m_Pop3Client; SetState(AsyncOP_State.Active); try{ /* RFC 1939 5. DELE Arguments: a message-number (required) which may NOT refer to a message marked as deleted Restrictions: may only be given in the TRANSACTION state Discussion: The POP3 server marks the message as deleted. Any future reference to the message-number associated with the message in a POP3 command generates an error. The POP3 server does not actually delete the message until the POP3 session enters the UPDATE state. Possible Responses: +OK message deleted -ERR no such message Examples: C: DELE 1 S: +OK message 1 deleted ... C: DELE 2 S: -ERR message 2 already deleted */ byte[] buffer = Encoding.UTF8.GetBytes("DELE " + owner.SequenceNumber.ToString() + "\r\n"); // Log m_pPop3Client.LogAddWrite(buffer.Length,"DELE " + owner.SequenceNumber.ToString()); // Start command sending. m_pPop3Client.TcpStream.BeginWrite(buffer,0,buffer.Length,this.DeleCommandSendingCompleted,null); } catch(Exception x){ m_pException = x; m_pPop3Client.LogAddException("Exception: " + x.Message,x); SetState(AsyncOP_State.Completed); } // Set flag rise CompletedAsync event flag. The event is raised when async op completes. // If already completed sync, that flag has no effect. lock(m_pLock){ m_RiseCompleted = true; return m_State == AsyncOP_State.Active; } }
private bool DecodeMessageAttachment(POP3_ClientMessage message) { bool _IsValid = false; var ro = new ReceiverObject(); //获取这封邮件的内容 byte[] bytes = message.MessageToByte(); //解析从Pop3服务器发送过来的邮件附件 Mime m = Mime.Parse(bytes); //二个月前的不接收了 if (m.MainEntity.Date < DateTime.Now.AddDays(-60)) { return false; } //遍历所有附件 foreach (MimeEntity me in m.Attachments) { //附件有效 if (!IsValidAttachment(me.ContentType_Name)) { continue; } //解压邮件 object obj = DeSerialObj(me.Data); if (obj != null) { ro.Objects.Add(obj); _IsValid = true; } } if (_IsValid) { _ReceiverObjects.Add(ro); ro.Message = message; } return _IsValid; }
private bool ProcessNewComment(List<string> recipients, POP3_ClientMessage message, Mail_Message mailHeader, MailboxReaderResult result) { string messageFrom = string.Empty; if (mailHeader.From.Count > 0) { messageFrom = string.Join("; ", mailHeader.From.ToList().Select(p => p.Address).ToArray()).Trim(); } bool processed = false; foreach (var address in recipients) { Regex isReply = new Regex(@"(.*)(\+iid-)(\d+)@(.*)"); Match commentMatch = isReply.Match(address); if (commentMatch.Success && commentMatch.Groups.Count >= 4) { // we are in a reply and group 4 must contain the id of the original issue int issueId; if (int.TryParse(commentMatch.Groups[3].Value, out issueId)) { var _currentIssue = IssueManager.GetById(issueId); if (_currentIssue != null) { var project = ProjectManager.GetById(_currentIssue.ProjectId); var mailbody = Mail_Message.ParseFromByte(message.MessageToByte()); bool isHtml; List<MIME_Entity> attachments = null; string content = GetMessageContent(mailbody, project, out isHtml, ref attachments); IssueComment comment = new IssueComment { IssueId = issueId, Comment = content, DateCreated = mailHeader.Date }; // try to find if the creator is valid user in the project, otherwise take // the user defined in the mailbox config var users = UserManager.GetUsersByProjectId(project.Id); var emails = messageFrom.Split(';').Select(e => e.Trim().ToLower()); var user = users.Find(x => emails.Contains(x.Email.ToLower())); if (user != null) { comment.CreatorUserName = user.UserName; } else { // user not found continue; } var saved = IssueCommentManager.SaveOrUpdate(comment); if (saved) { //add history record var history = new IssueHistory { IssueId = issueId, CreatedUserName = comment.CreatorUserName, DateChanged = comment.DateCreated, FieldChanged = ResourceStrings.GetGlobalResource(GlobalResources.SharedResources, "Comment", "Comment"), OldValue = string.Empty, NewValue = ResourceStrings.GetGlobalResource(GlobalResources.SharedResources, "Added", "Added"), TriggerLastUpdateChange = true }; IssueHistoryManager.SaveOrUpdate(history); var projectFolderPath = Path.Combine(Config.UploadsFolderPath, project.UploadPath); // save attachments as new files int attachmentsSavedCount = 1; foreach (MIME_Entity mimeEntity in attachments) { string fileName; var contentType = mimeEntity.ContentType.Type.ToLower(); var attachment = new IssueAttachment { Id = 0, Description = "File attached by mailbox reader", DateCreated = DateTime.Now, ContentType = mimeEntity.ContentType.TypeWithSubtype, CreatorDisplayName = user.DisplayName, CreatorUserName = user.UserName, IssueId = issueId, ProjectFolderPath = projectFolderPath }; attachment.Attachment = ((MIME_b_SinglepartBase)mimeEntity.Body).Data; if (contentType.Equals("attachment")) // this is an attached email { fileName = mimeEntity.ContentDisposition.Param_FileName; } else if (contentType.Equals("message")) // message has no filename so we create one { fileName = string.Format("Attached_Message_{0}.eml", attachmentsSavedCount); } else { fileName = string.IsNullOrWhiteSpace(mimeEntity.ContentType.Param_Name) ? string.Format("untitled.{0}", mimeEntity.ContentType.SubType) : mimeEntity.ContentType.Param_Name; } attachment.FileName = fileName; var saveFile = IsAllowedFileExtension(fileName); var fileSaved = false; // can we save the file? if (saveFile) { fileSaved = IssueAttachmentManager.SaveOrUpdate(attachment); if (fileSaved) { attachmentsSavedCount++; } else { LogWarning("MailboxReader: Attachment could not be saved, please see previous logs"); } } } processed = true; // add the entry if the save did not throw any exceptions result.MailboxEntries.Add(new MailboxEntry()); } } } } } return processed; }
private bool ProcessNewIssue(List<string> recipients, POP3_ClientMessage message, Mail_Message mailHeader, IList<Project> projects, MailboxReaderResult result) { var messageFrom = string.Empty; if (mailHeader.From.Count > 0) { messageFrom = string.Join("; ", mailHeader.From.ToList().Select(p => p.Address).ToArray()).Trim(); } bool processed = false; // loop through the mailboxes foreach (var address in recipients) { var pmbox = ProjectMailboxManager.GetByMailbox(address); // cannot find the mailbox skip the rest if (pmbox == null) { LogWarning(string.Format("MailboxReader: could not find project mailbox: {0} skipping.", address)); continue; } var project = projects.FirstOrDefault(p => p.Id == pmbox.ProjectId); if (project == null) { project = ProjectManager.GetById(pmbox.ProjectId); // project is disabled skip if (project.Disabled) { LogWarning(string.Format("MailboxReader: Project {0} - {1} is flagged as disabled skipping.", project.Id, project.Code)); continue; } projects.Add(project); } var entry = new MailboxEntry { Title = mailHeader.Subject.Trim(), From = messageFrom, ProjectMailbox = pmbox, Date = mailHeader.Date, Project = project, Content = "Email Body could not be parsed." }; var mailbody = Mail_Message.ParseFromByte(message.MessageToByte()); bool isHtml; List<MIME_Entity> attachments = null; string content = GetMessageContent(mailbody, project, out isHtml, ref attachments); entry.Content = content; entry.IsHtml = isHtml; foreach (var attachment in attachments) { entry.MailAttachments.Add(attachment); } //save this message Issue issue = SaveMailboxEntry(entry); //send notifications for the new issue SendNotifications(issue); // add the entry if the save did not throw any exceptions result.MailboxEntries.Add(entry); processed = true; } return processed; }
/// <summary> /// Cleans up any resources being used. /// </summary> public void Dispose() { if(m_State == AsyncOP_State.Disposed){ return; } SetState(AsyncOP_State.Disposed); m_pException = null; m_pOwner = null; m_pPop3Client = null; m_pStream = null; this.CompletedAsync = null; }
/// <summary> /// Starts operation processing. /// </summary> /// <param name="owner">Owner POP3 client message.</param> /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns> /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception> internal bool Start(POP3_ClientMessage owner) { if(owner == null){ throw new ArgumentNullException("owner"); } m_pOwner = owner; m_pPop3Client = owner.m_Pop3Client; SetState(AsyncOP_State.Active); try{ /* RFC 1939 5. RETR Arguments: a message-number (required) which may NOT refer to a message marked as deleted Restrictions: may only be given in the TRANSACTION state Discussion: If the POP3 server issues a positive response, then the response given is multi-line. After the initial +OK, the POP3 server sends the message corresponding to the given message-number, being careful to byte-stuff the termination character (as with all multi-line responses). Possible Responses: +OK message follows -ERR no such message Examples: C: RETR 1 S: +OK 120 octets S: <the POP3 server sends the entire message here> S: . */ byte[] buffer = Encoding.UTF8.GetBytes("RETR " + owner.SequenceNumber.ToString() + "\r\n"); // Log m_pPop3Client.LogAddWrite(buffer.Length,"RETR " + owner.SequenceNumber.ToString()); // Start command sending. m_pPop3Client.TcpStream.BeginWrite(buffer,0,buffer.Length,this.RetrCommandSendingCompleted,null); } catch(Exception x){ m_pException = x; m_pPop3Client.LogAddException("Exception: " + x.Message,x); SetState(AsyncOP_State.Completed); } // Set flag rise CompletedAsync event flag. The event is raised when async op completes. // If already completed sync, that flag has no effect. lock(m_pLock){ m_RiseCompleted = true; return m_State == AsyncOP_State.Active; } }
/// <summary> /// Starts operation processing. /// </summary> /// <param name="owner">Owner POP3 client message.</param> /// <returns>Returns true if asynchronous operation in progress or false if operation completed synchronously.</returns> /// <exception cref="ArgumentNullException">Is raised when <b>owner</b> is null reference.</exception> internal bool Start(POP3_ClientMessage owner) { if(owner == null){ throw new ArgumentNullException("owner"); } m_pOwner = owner; m_pPop3Client = owner.m_Pop3Client; SetState(AsyncOP_State.Active); try{ /* RFC 1939 7. TOP Arguments: a message-number (required) which may NOT refer to to a message marked as deleted, and a non-negative number of lines (required) Restrictions: may only be given in the TRANSACTION state Discussion: If the POP3 server issues a positive response, then the response given is multi-line. After the initial +OK, the POP3 server sends the headers of the message, the blank line separating the headers from the body, and then the number of lines of the indicated message's body, being careful to byte-stuff the termination character (as with all multi-line responses). Note that if the number of lines requested by the POP3 client is greater than than the number of lines in the body, then the POP3 server sends the entire message. Possible Responses: +OK top of message follows -ERR no such message Examples: C: TOP 1 10 S: +OK S: <the POP3 server sends the headers of the message, a blank line, and the first 10 lines of the body of the message> S: . ... C: TOP 100 3 S: -ERR no such message */ byte[] buffer = Encoding.UTF8.GetBytes("TOP " + owner.SequenceNumber.ToString()+ " " + m_LineCount.ToString() + "\r\n"); // Log m_pPop3Client.LogAddWrite(buffer.Length,"TOP " + owner.SequenceNumber.ToString()+ " " + m_LineCount.ToString()); // Start command sending. m_pPop3Client.TcpStream.BeginWrite(buffer,0,buffer.Length,this.TopCommandSendingCompleted,null); } catch(Exception x){ m_pException = x; m_pPop3Client.LogAddException("Exception: " + x.Message,x); SetState(AsyncOP_State.Completed); } // Set flag rise CompletedAsync event flag. The event is raised when async op completes. // If already completed sync, that flag has no effect. lock(m_pLock){ m_RiseCompleted = true; return m_State == AsyncOP_State.Active; } }