예제 #1
0
        /// <summary>
        /// Reads the mail.
        /// </summary>
        public void ReadMail()
        {
            Pop3MimeClient mailClient = new Pop3MimeClient(_Server, _Port, _UseSSL, _Username, _Password);

            try
            {
                mailClient.Connect();
                List<int> messageIds;
                mailClient.GetEmailIdList(out messageIds);

                for (int i = 0; i < messageIds.Count; i++)
                {
                    bool messageWasProcessed = false;
                    RxMailMessage message;

                    if (mailClient.GetEmail(messageIds[i], out message))
                    {
                        string messageFrom = string.Empty;

                        if (message.From.Address.Length > 0)
                        {
                            messageFrom = message.From.Address;
                        }

                        List<string> recipients = new List<string>();

                        foreach (MailAddress address in message.To)
                            recipients.Add(address.Address);
                        foreach (MailAddress address in message.CC)
                            recipients.Add(address.Address);
                        foreach (MailAddress address in message.Bcc)
                            recipients.Add(address.Address);

                        foreach (string mailbox in recipients)
                        {
                            ProjectMailbox pmbox = ProjectMailboxManager.GetByMailbox(mailbox);
                            if (pmbox != null)
                            {
                                MailboxEntry entry = new MailboxEntry();
                                Project project = ProjectManager.GetById(pmbox.ProjectId);

                                //TODO: Enhancements could include regex / string matching or not matching
                                //for particular strings values in the subject or body.
                                entry.Title = message.Subject.Trim();
                                entry.From = messageFrom;
                                entry.ProjectMailbox = pmbox;
                                entry.Date = message.DeliveryDate;

                                if (message.Entities.Count > 0)
                                {
                                    //find if there is an html version.
                                    if (message.Entities.FindAll(m => m.IsBodyHtml).Count > 0)
                                    {
                                        List<RxMailMessage> htmlMessages = message.Entities.FindAll(m => m.IsBodyHtml);
                                        if (htmlMessages.Count > 0)
                                            message = htmlMessages[0];
                                    }

                                }
                                if (!message.IsBodyHtml)
                                    entry.Content.Append(message.Body.Replace("\n", "<br />"));
                                else
                                {
                                    // Strip the <body> out of the message (using code from below)
                                    Regex bodyExtractor = new Regex("<body.*?>(?<content>.*)</body>", RegexOptions.IgnoreCase | RegexOptions.Singleline);
                                    Match match = bodyExtractor.Match(message.Body);
                                    if (match != null && match.Success && match.Groups["content"] != null)
                                    {
                                        entry.Content.Append(match.Groups["content"].Value);
                                    }
                                    else
                                    {
                                        entry.Content.Append(message.Body);
                                    }
                                }

                                if (_ProcessAttachments)
                                {
                                    foreach (Attachment attachment in message.Attachments)
                                    {
                                        if (attachment.ContentStream != null && attachment.ContentDisposition.FileName != null && attachment.ContentDisposition.FileName.Length > 0)
                                        {
                                            entry.MailAttachments.Add(attachment);
                                        }
                                    }
                                }

                                //save this message the mark the message as processed
                                SaveMailboxEntry(entry);
                                messageWasProcessed = true;

                                //if delete all messages AND the message was processed delete the message from the server.
                                if (_DeleteAllMessages && messageWasProcessed)
                                    mailClient.DeleteEmail(i);
                            }
                            else
                            {
                                if (Log.IsWarnEnabled)
                                    Log.WarnFormat("Project Mailbox Not Found: {0}", message.To.ToString());
                            }
                        }
                    }

                }
            }
            catch (Exception ex)
            {
                if (Log.IsErrorEnabled)
                    Log.Error("Mailbox Reader Error", ex);
            }
            finally
            {
                try
                {
                    mailClient.Disconnect();
                }
                catch
                { }
            }
        }
예제 #2
0
        /// <summary>
        /// Saves the mailbox entry.
        /// </summary>
        /// <param name="entry">The entry to be saved</param>
        Issue SaveMailboxEntry(MailboxEntry entry)
        {
            try
            {
                //load template 
                var body = string.Format("<div >Sent by:{1} on: {2}<br/>{0}</div>", entry.Content.Trim(), entry.From, entry.Date);

                if (Config.BodyTemplate.Trim().Length > 0)
                {
                    var data = new Dictionary<string, object> { { "MailboxEntry", entry } };
                    body = NotificationManager.GenerateNotificationContent(Config.BodyTemplate, data);
                }

                var projectId = entry.ProjectMailbox.ProjectId;

                // try to find if the creator is valid user in the project, otherwise take
                // the user defined in the mailbox config
                var creator = Config.ReportingUserName;
                var users = UserManager.GetUsersByProjectId(projectId);
                var emails = entry.From.Split(';').Select(e => e.Trim().ToLower());
                var user = users.Find(x => emails.Contains(x.Email.ToLower()));
                if (user != null)
                    creator = user.UserName;

                var mailIssue = IssueManager.GetDefaultIssueByProjectId(
                    projectId,
                    entry.Title.Trim(),
                    body.Trim(),
                    entry.ProjectMailbox.IssueTypeId,
                    entry.ProjectMailbox.AssignToUserName,
                    creator);

                if (entry.ProjectMailbox.CategoryId != 0)
                {
                    // overwrite default category with mailbox category
                    mailIssue.CategoryId = entry.ProjectMailbox.CategoryId;
                }

                if (!IssueManager.SaveOrUpdate(mailIssue)) return null;

                entry.IssueId = mailIssue.Id;
                entry.WasProcessed = true;

                var project = ProjectManager.GetById(projectId);

                var projectFolderPath = Path.Combine(Config.UploadsFolderPath, project.UploadPath);

                var doc = new HtmlDocument();
                doc.LoadHtml(mailIssue.Description); // load the issue body to we can process it for inline images (if exist)

                //If there is an attached file present then add it to the database 
                //and copy it to the directory specified in the web.config file
                foreach (MIME_Entity mimeEntity in entry.MailAttachments)
                {
                    string fileName;
                    var isInline = false;
                    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 = Config.ReportingUserName,
                            CreatorUserName = Config.ReportingUserName,
                            IssueId = mailIssue.Id,
                            ProjectFolderPath = projectFolderPath
                        };

                    switch (contentType)
                    {
                        case "application":
                            attachment.Attachment = ((MIME_b_SinglepartBase)mimeEntity.Body).Data;
                            break;
                        case "attachment":
                        case "image":
                        case "video":
                        case "audio":

                            attachment.Attachment = ((MIME_b_SinglepartBase)mimeEntity.Body).Data;
                            break;
                        case "message":

                            // we need to pull the actual email message out of the entity, and strip the "content type" out so that
                            // email programs will read the file properly
                            var messageBody = mimeEntity.ToString().Replace(mimeEntity.Header.ToString(), "");
                            if (messageBody.StartsWith("\r\n"))
                            {
                                messageBody = messageBody.Substring(2);
                            }

                            attachment.Attachment = Encoding.UTF8.GetBytes(messageBody);

                            break;
                        default:
                            LogWarning(string.Format("MailboxReader: Attachment type could not be processed {0}", mimeEntity.ContentType.Type));
                            break;
                    }

                    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", entry.AttachmentsSavedCount);
                    }
                    else
                    {
                        isInline = true;
                        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)
                        {
                            entry.AttachmentsSavedCount++;
                        }
                        else
                        {
                            LogWarning("MailboxReader: Attachment could not be saved, please see previous logs");
                        }
                    }

                    if (!entry.IsHtml || !isInline) continue;

                    if (string.IsNullOrWhiteSpace(mimeEntity.ContentID)) continue;

                    var contentId = mimeEntity.ContentID.Replace("<", "").Replace(">", "").Replace("[", "").Replace("]", "");

                    // this is pretty greedy but since people might be sending screenshots I doubt they will send in dozens of images
                    // embedded in the email.  one would hope
                    foreach (var node in doc.DocumentNode.SelectNodes(XpathElementCaseInsensitive("img")).ToList())
                    {
                        var attr = node.Attributes.FirstOrDefault(p => p.Name.ToLowerInvariant() == "src");// get the src attribute

                        if (attr == null) continue; // image has no src attribute
                        if (!attr.Value.Contains(contentId)) continue; // is the attribute value the content id?

                        // swap out the content of the parent node html will our link to the image
                        var anchor = string.Format("<span class='inline-mail-attachment'>Inline Attachment: <a href='DownloadAttachment.axd?id={0}' target='_blank'>{1}</a></span>", attachment.Id, fileName);

                        // for each image in the body if the file was saved swap out the inline link for a link to the saved attachment
                        // otherwise blank out the content link so we don't get a missing image link
                        node.ParentNode.InnerHtml = fileSaved ? anchor : "";
                    }

                    mailIssue.Description = doc.DocumentNode.InnerHtml;
                    mailIssue.LastUpdateUserName = mailIssue.OwnerUserName;
                    mailIssue.LastUpdate = DateTime.Now;

                    IssueManager.SaveOrUpdate(mailIssue);
                }

                return mailIssue;
            }
            catch (Exception ex)
            {
                LogException(ex);
                throw;
            }
        }
예제 #3
0
        /// <summary>
        /// Saves the mailbox entry.
        /// </summary>
        /// <param name="entry">The entry.</param>
        public void SaveMailboxEntry(MailboxEntry entry)
        {
            try
            {
                // TODO Should use XSLT templates BGN-1591
                string body = string.Format(this._BodyTemplate, entry.Content.ToString().Trim(), entry.From, entry.Date.ToString());
                int projectId = entry.ProjectMailbox.ProjectId;

                var mailIssue = IssueManager.GetDefaultIssueByProjectId(projectId, entry.Title.Trim(), body.Trim(), entry.ProjectMailbox.AssignToUserName, this._ReportingUserName);

                if (IssueManager.SaveOrUpdate(mailIssue))
                {
                    //If there is an attached file present then add it to the database
                    //and copy it to the directory specified in the web.config file
                    foreach (Attachment attMail in entry.MailAttachments)
                    {
                        var attachmentBytes = new byte[attMail.ContentStream.Length];
                        ReadWholeArray(attMail.ContentStream, attachmentBytes);

                        var attachment = new IssueAttachment()
                                             {
                                                 Id = 0,
                                                 Attachment = attachmentBytes,
                                                 Description = "Attached via email",
                                                 DateCreated = DateTime.Now,
                                                 ContentType = attMail.ContentType.ToString(),
                                                 CreatorDisplayName = _ReportingUserName,
                                                 CreatorUserName = _ReportingUserName,
                                                 FileName = attMail.ContentDisposition.FileName,
                                                 IssueId = mailIssue.Id,
                                                 Size = attachmentBytes.Length
                                             };

                        if (!IssueAttachmentManager.SaveOrUpdate(attachment))
                            if (Log.IsWarnEnabled) Log.Warn("Attachment was not added via mailbox reader");
                    }
                }
            }
            catch (Exception ex)
            {
                throw ProcessException(ex);
            }
        }
예제 #4
0
        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;
        }