| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 | using InABox.Core;using MailKit;using MailKit.Net.Imap;using MailKit.Net.Smtp;using MimeKit;namespace InABox.Mail{    public class IMAPMailer : CoreMailer<IMAPMailFolder, IMAPMailSummary, IMAPMailMessage>    {        private static ProtocolLogger imaplog;        private static ProtocolLogger smtplog;        private ImapClient _client;        protected override void Initialize()        {            if (imaplog == null)                imaplog = new ProtocolLogger(Path.Combine(CoreUtils.GetPath(), "imap.log"));            _client = new ImapClient(imaplog);            _client.ServerCertificateValidationCallback = (s, c, h, e) => true;        }        public override void Dispose()        {            if (_client.IsConnected)                _client.Disconnect(true);            _client.Dispose();            _client = null;        }        protected override bool DoConnect()        {            try            {                if (_client.IsConnected)                    return true;                _client.Connect(MailboxHost, MailboxPort == 0 ? 993 : MailboxPort, MailboxPort != 143);                _client.Authenticate(MailboxUserName, MailboxPassword);                return true;            }            catch (Exception e)            {                return false;            }        }        protected override bool GetIsConnected()        {            return _client.IsConnected;        }        protected override IMAPMailMessage DoCreateMessage()        {            return new IMAPMailMessage(null, UniqueId.MinValue, new MimeMessage());        }        protected override IMAPMailFolder DoFindFolder(IMAPMailFolder parent, string name)        {            if (string.IsNullOrEmpty(name))                return parent;            return new IMAPMailFolder(parent.Folder.GetSubfolder(name));        }        protected override IMAPMailFolder GetInbox()        {            return new IMAPMailFolder(_client.Inbox);        }        protected override IMAPMailFolder GetSentItems()        {            if ((_client.Capabilities & (ImapCapabilities.SpecialUse | ImapCapabilities.XList)) != 0)                return new IMAPMailFolder(_client.GetFolder(SpecialFolder.Sent));            string[] CommonSentFolderNames = { "Sent", "Sent Items", "Sent Mail", "Sent Messages" /* maybe add some translated names */ };            var personal = _client.GetFolder(_client.PersonalNamespaces[0]);            var folder = personal.GetSubfolders().FirstOrDefault(x => CommonSentFolderNames.Contains(x.Name));            if (folder != null)                return new IMAPMailFolder(folder);            throw new Exception("Cannot find Sent Items Folder!");        }        protected override IMAPMailMessage DoGetMessage(IMAPMailFolder folder, string id)        {            var fld = folder != null ? folder.Folder : _client.Inbox;            if (!fld.IsOpen)                fld.Open(FolderAccess.ReadWrite);            var uid = UniqueId.Parse(id);            var msg = fld.GetMessage(uid);            return new IMAPMailMessage(fld, uid, msg);        }        protected override IEnumerable<IMAPMailMessage> DoGetMessages(IMAPMailFolder folder)        {            var results = new List<IMAPMailMessage>();            var fld = folder != null ? folder.Folder : _client.Inbox;            if (!fld.IsOpen)                fld.Open(FolderAccess.ReadWrite);            var summaries = fld.Fetch(0, -1, MessageSummaryItems.UniqueId | MessageSummaryItems.Flags);            foreach (var summary in summaries)                if (!summary.Flags.HasValue || !summary.Flags.Value.HasFlag(MessageFlags.Deleted))                {                    var msg = fld.GetMessage(summary.UniqueId);                    results.Add(new IMAPMailMessage(fld, summary.UniqueId, msg));                }            return results;        }        protected override IEnumerable<IMAPMailSummary> DoListMessages(IMAPMailFolder folder, int min = 0, int max = int.MaxValue)        {            var fld = folder != null ? folder.Folder : _client.Inbox;            if (!fld.IsOpen)                fld.Open(FolderAccess.ReadOnly);            var summaries = fld.Fetch(min, max, MessageSummaryItems.UniqueId | MessageSummaryItems.Flags | MessageSummaryItems.Envelope);            return summaries.Where(x => !x.Flags.Value.HasFlag(MessageFlags.Deleted)).Select(x => new IMAPMailSummary(fld, x));        }        protected override bool DoMoveMessage(IMAPMailMessage message, IMAPMailFolder to)        {            message.Move(to != null ? to.Folder : _client.Inbox);            return true;        }        private bool UsesSSL(int port)        {            return port != 25;        }        protected override bool DoSendMessage(IMAPMailMessage message)        {            if (smtplog == null)                smtplog = new ProtocolLogger(Path.Combine(CoreUtils.GetPath(), "smtp.log"));            using (var smtp = new SmtpClient(smtplog))            {                smtp.ServerCertificateValidationCallback = (s, c, h, e) => true;                smtp.Connect(SMTPHost, SMTPPort == 0 ? 587 : SMTPPort, SMTPPort == 465);                smtp.Authenticate(SMTPUserName, SMTPPassword);                smtp.Send(message.Message);                if ((_client.Capabilities & (ImapCapabilities.SpecialUse | ImapCapabilities.XList)) != 0)                {                    var sent = _client.GetFolder(SpecialFolder.Sent);                    sent.Open(FolderAccess.ReadWrite);                    var id = sent.Append(message.Message).Value;                    sent.SetFlags(id, MessageFlags.Seen, true);                }                smtp.Disconnect(true);            }            return true;        }        protected override bool DoSaveDraft(IMAPMailMessage message)        {            var draftFolder = _client.GetFolder(SpecialFolder.Drafts);            if (draftFolder == null)            {                var toplevel = _client.GetFolder(_client.PersonalNamespaces[0]);                draftFolder = toplevel.Create(SpecialFolder.Drafts.ToString(), true);            }            message.Move(draftFolder);            draftFolder.SetFlags(message.UniqueID, MessageFlags.Draft, true);            draftFolder.Expunge();            return true;        }    }}
 |