diff options
Diffstat (limited to 'utils/smtp/session.go')
| -rw-r--r-- | utils/smtp/session.go | 108 |
1 files changed, 106 insertions, 2 deletions
diff --git a/utils/smtp/session.go b/utils/smtp/session.go index 73fc4e1..ef5ddc7 100644 --- a/utils/smtp/session.go +++ b/utils/smtp/session.go @@ -2,9 +2,16 @@ package smtp import ( "dove/config" + mailModel "dove/models/mail" + mailRepo "dove/repositories/mail" + "dove/utils/email" "dove/utils/errors" "dove/utils/logger" + "dove/utils/storage" + "fmt" "io" + "strings" + "time" gosmtp "github.com/emersion/go-smtp" ) @@ -45,9 +52,41 @@ func (self *Session) Data(messageReader io.Reader) error { return readError } - logger.Infof(LogPrefix, MessageReceived, len(rawMessage)) + logger.Infof(LogPrefix, MessageReceived, len(rawMessage), self.fromAddress, self.toAddresses) - _ = rawMessage + parsedEmail, parseError := email.Parse(rawMessage) + if parseError != nil { + logger.Errorf(LogPrefix, MessageParseFailed, parseError) + return parseError + } + + deliveredToLocal := false + + for _, recipientAddress := range self.toAddresses { + recipientMailbox := mailRepo.FindMailboxByAddress(recipientAddress) + if recipientMailbox == nil { + aliasMailbox := mailRepo.FindMailboxByAlias(recipientAddress) + if aliasMailbox != nil { + recipientMailbox = aliasMailbox + } + } + + if recipientMailbox != nil { + deliverError := deliverToLocalMailbox(recipientMailbox, parsedEmail, rawMessage) + if deliverError != nil { + logger.Errorf(LogPrefix, DeliveryFailed, recipientAddress, deliverError) + continue + } + logger.Infof(LogPrefix, DeliverySuccess, recipientAddress) + deliveredToLocal = true + } else { + logger.Debugf(LogPrefix, RecipientNotLocal, recipientAddress) + } + } + + if !deliveredToLocal { + logger.Warnf(LogPrefix, NoLocalRecipients, self.fromAddress) + } return nil } @@ -60,3 +99,68 @@ func (self *Session) Reset() { func (self *Session) Logout() error { return nil } + +func deliverToLocalMailbox(mailbox *mailModel.Mailbox, parsedEmail *email.ParsedEmail, rawMessage []byte) error { + inboxFolder := mailRepo.FindFolderBySlug(mailbox.ID, "inbox") + if inboxFolder == nil { + return errors.Error("Inbox folder not found for mailbox %s.", mailbox.Address) + } + + filename := fmt.Sprintf("%d", time.Now().UnixNano()) + + toAddressesJoined := strings.Join(parsedEmail.ToAddresses, ", ") + ccAddressesJoined := strings.Join(parsedEmail.CcAddresses, ", ") + bccAddressesJoined := strings.Join(parsedEmail.BccAddresses, ", ") + + attachmentCount := 0 + inlineCount := 0 + for _, attachment := range parsedEmail.Attachments { + if attachment.IsInline { + inlineCount++ + } else { + attachmentCount++ + } + } + + emailRecord := &mailModel.Email{ + MailboxID: mailbox.ID, + FolderID: inboxFolder.ID, + MessageID: parsedEmail.MessageID, + Filename: filename, + FromAddress: parsedEmail.FromAddress, + FromName: parsedEmail.FromName, + ToAddresses: toAddressesJoined, + CcAddresses: ccAddressesJoined, + BccAddresses: bccAddressesJoined, + ReplyToAddress: parsedEmail.ReplyToAddress, + ReturnPath: parsedEmail.ReturnPath, + Subject: parsedEmail.Subject, + Snippet: parsedEmail.Snippet, + Size: parsedEmail.Size, + IsRead: false, + AttachmentCount: attachmentCount, + InlineCount: inlineCount, + } + + if createError := mailRepo.CreateEmail(emailRecord); createError != nil { + return createError + } + + for _, parsedAttachment := range parsedEmail.Attachments { + attachmentRecord := &mailModel.Attachment{ + EmailID: emailRecord.ID, + Filename: parsedAttachment.Filename, + ContentType: parsedAttachment.ContentType, + ContentID: parsedAttachment.ContentID, + Size: parsedAttachment.Size, + IsInline: parsedAttachment.IsInline, + } + mailRepo.CreateAttachment(attachmentRecord) + } + + if writeError := storage.WriteMailFile(mailbox.Address, "inbox", filename, rawMessage); writeError != nil { + logger.Warnf(LogPrefix, MessageStoreFailed, writeError) + } + + return nil +} |
