public async Task SendEmail(string email, string subject, string htmlMessage) { try { using MailKit.IMailTransport mailTransport = await CreateTransport(); InternetAddressList fromList = new InternetAddressList(); fromList.Add(new MailboxAddress(_Settings.SenderDisplayName, _Settings.SenderEmail)); InternetAddressList toList = new InternetAddressList(); toList.AddRange(email.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Select(ma => new MailboxAddress(ma, ma))); BodyBuilder bodyBuilder = new BodyBuilder(); bodyBuilder.HtmlBody = htmlMessage; bodyBuilder.TextBody = htmlMessage; MimeMessage mimeMessage = new MimeMessage(fromList, toList, subject, bodyBuilder.ToMessageBody()); await mailTransport.SendAsync(mimeMessage); } catch (AggregateException ae) { _Logger.LogError($"Aggregate exception when sending email. Email host {_Settings.SmtpMailServer}:{_Settings.SmtpPort}", ae.Flatten()); throw; } catch (AuthenticationException authe) { _Logger.LogError($"Authentification failed.\n {authe.Message}\n Email host {_Settings.SmtpMailServer}:{_Settings.SmtpPort}", authe); throw; } catch (Exception e) { _Logger.LogError($"Exception of type '{e.GetType().Name}' when sending email. Email host {_Settings.SmtpMailServer}:{_Settings.SmtpPort}", e); throw; } }
private void SetRecipientsEmailAddresses(InternetAddressList list, IEnumerable <string>?addresses) { if (addresses == null) { return; } list.AddRange(addresses.Select(MailboxAddress.Parse)); }
private static void CopyAddressList(MailAddressCollection sourceList, InternetAddressList targetList, MimeMessage message, HeaderId headerId) { if (sourceList == null || sourceList.Count == 0) { return; } message.Headers.Replace(headerId, string.Empty); targetList.AddRange(sourceList.Select(ToMailboxAddress).Where(t => t != null)); }
public virtual async Task RunAsync(CancellationToken cancellationToken) { var to = new InternetAddressList(); var cc = new InternetAddressList(); var bcc = new InternetAddressList(); var mailSender = MailMergeService.Sender; // there's always a new instance returned! var onBeforeSend = new EventHandler <MailSenderBeforeSendEventArgs>((sender, args) => { to.AddRange(args.MimeMessage.To); cc.AddRange(args.MimeMessage.Cc); bcc.AddRange(args.MimeMessage.Bcc); }); mailSender.OnBeforeSend += onBeforeSend; try { if (MailData is IEnumerable <object> mailData) { cancellationToken.ThrowIfCancellationRequested(); await mailSender.SendAsync <object>(MailMessage, mailData); } else { cancellationToken.ThrowIfCancellationRequested(); await mailSender.SendAsync(MailMessage, MailData); } Logger.LogInformation($"Mail sent. TO: {to} - CC: {cc} - BCC: {bcc}"); } catch (Exception e) when(e is TaskCanceledException || e is OperationCanceledException) { Logger.LogError(e, "Mail failure. TO: {to} - CC: {cc} - BCC: {bcc}\nSubject: {subject}\nMessage: {message}", to, cc, bcc, MailMessage.Subject, MailMessage.PlainText); mailSender.SendCancel(); throw; } catch (Exception e) { Logger.LogError(e, "Mail failure. TO: {to} - CC: {cc} - BCC: {bcc}\nSubject: {subject}\nMessage: {message}", to, cc, bcc, MailMessage.Subject, MailMessage.PlainText); throw; } finally { MailMergeService.Sender.OnBeforeSend -= onBeforeSend; to.Clear(); cc.Clear(); bcc.Clear(); } }
public void TestArgumentExceptions() { var mailbox = new MailboxAddress("MimeKit Unit Tests", "*****@*****.**"); var list = new InternetAddressList(); list.Add(new MailboxAddress("Example User", "*****@*****.**")); Assert.Throws <ArgumentNullException> (() => new InternetAddressList(null)); Assert.Throws <ArgumentNullException> (() => list.Add(null)); Assert.Throws <ArgumentNullException> (() => list.AddRange(null)); Assert.Throws <ArgumentNullException> (() => list.CompareTo(null)); Assert.Throws <ArgumentNullException> (() => list.Contains(null)); Assert.Throws <ArgumentNullException> (() => list.CopyTo(null, 0)); Assert.Throws <ArgumentOutOfRangeException> (() => list.CopyTo(new InternetAddress[0], -1)); Assert.Throws <ArgumentNullException> (() => list.IndexOf(null)); Assert.Throws <ArgumentOutOfRangeException> (() => list.Insert(-1, mailbox)); Assert.Throws <ArgumentNullException> (() => list.Insert(0, null)); Assert.Throws <ArgumentNullException> (() => list.Remove(null)); Assert.Throws <ArgumentOutOfRangeException> (() => list.RemoveAt(-1)); Assert.Throws <ArgumentOutOfRangeException> (() => list[-1] = mailbox); Assert.Throws <ArgumentNullException> (() => list[0] = null); }
public void TestArgumentExceptions () { var mailbox = new MailboxAddress ("MimeKit Unit Tests", "*****@*****.**"); var list = new InternetAddressList (); list.Add (new MailboxAddress ("Example User", "*****@*****.**")); Assert.Throws<ArgumentNullException> (() => new InternetAddressList (null)); Assert.Throws<ArgumentNullException> (() => list.Add (null)); Assert.Throws<ArgumentNullException> (() => list.AddRange (null)); Assert.Throws<ArgumentNullException> (() => list.CompareTo (null)); Assert.Throws<ArgumentNullException> (() => list.Contains (null)); Assert.Throws<ArgumentNullException> (() => list.CopyTo (null, 0)); Assert.Throws<ArgumentOutOfRangeException> (() => list.CopyTo (new InternetAddress[0], -1)); Assert.Throws<ArgumentNullException> (() => list.IndexOf (null)); Assert.Throws<ArgumentOutOfRangeException> (() => list.Insert (-1, mailbox)); Assert.Throws<ArgumentNullException> (() => list.Insert (0, null)); Assert.Throws<ArgumentNullException> (() => list.Remove (null)); Assert.Throws<ArgumentOutOfRangeException> (() => list.RemoveAt (-1)); Assert.Throws<ArgumentOutOfRangeException> (() => list[-1] = mailbox); Assert.Throws<ArgumentNullException> (() => list[0] = null); }
void ReloadAddressList (HeaderId id, InternetAddressList list) { // clear the address list and reload list.Changed -= InternetAddressListChanged; list.Clear (); foreach (var header in Headers) { if (header.Id != id) continue; int length = header.RawValue.Length; List<InternetAddress> parsed; int index = 0; if (!InternetAddressList.TryParse (Headers.Options, header.RawValue, ref index, length, false, false, out parsed)) continue; list.AddRange (parsed); } list.Changed += InternetAddressListChanged; }
void AddAddresses (Header header, InternetAddressList list) { int length = header.RawValue.Length; List<InternetAddress> parsed; int index = 0; // parse the addresses in the new header and add them to our address list if (!InternetAddressList.TryParse (Headers.Options, header.RawValue, ref index, length, false, false, out parsed)) return; list.Changed -= InternetAddressListChanged; list.AddRange (parsed); list.Changed += InternetAddressListChanged; }
/// <summary> /// Asynchronously produces e-mails and notification messages for all intended recipients based on the specified event type. /// </summary> /// <param name="args">An object that holds issue-related event data.</param> /// <param name="cancellationToken">The token used to cancel an ongoing async operation.</param> /// <returns></returns> public override async Task ProcessAsync(SysEventArgs args, CancellationToken cancellationToken = default(CancellationToken)) { // give a chance to the base message producer to process the event await base.ProcessAsync(args, cancellationToken); if (!(args is SysEventArgs <Issue> e)) { throw new ArgumentException($"Must be of type {nameof(SysEventArgs<Issue>)}.", nameof(args)); } var issue = e.Data ?? throw new ArgumentNullException("Data"); var user = (e.User as AppUser) ?? throw new ArgumentNullException("User"); var settings = e.ObjectState as EmailSettingsViewModel ?? throw new ArgumentNullException("ObjectState", $"ObjectState must be of type {nameof(EmailSettingsViewModel)}"); var notifs = settings.Notifications; _emailNotificationsEnabled = notifs.Enabled ?? false; try { if (issue.User == null && e.EventType != SysEventType.IssueDeleted) { issue = await _issueRepo.All(q => q.QueryIssues(id: issue.Id, withIncludes: true)).SingleOrDefaultAsync(); } var fullName = user.FullName(); var userName = user.UserName; var notify = false; var outgoing = settings.Outgoing; var from = outgoing.FromDisplay; var useFromNameForAll = outgoing.UseFromNameForAll ?? false; var replyToAddrList = new InternetAddressList(); if (!string.IsNullOrWhiteSpace(outgoing.ReplyTo)) { replyToAddrList.AddRange(outgoing.ReplyTo); } EmailTemplate temp; var templates = settings.Templates; switch (e.EventType) { case SysEventType.IssueCreated: { // Sent to technicians when a new ticket arrives. All technicians that have permissions to the category get one of these. // Ticket confirmation notification (the one users get after submitting a new ticket)? notify = notifs.TicketConfirmationNotification ?? false; if (notify && user.SendEmail && user.EmailConfirmed) { // "Ticket confirmation" email template: Sent to the ticket-submitter after the app received his ticket. temp = templates.TicketConfirmation; var m = CreateMessage( temp.ReplaceSubject(issue.Subject).ToString(), temp.ReplaceBody(issue.Body, issue.Subject) .Replace("#Numero_ticket#", $"{issue.Id}") .Replace("#Articles_Base_Connaissances#", string.Empty) //.Replace("#Suggested_KB_articles#", string.Empty) .ToString(), from, to: user.Email ); m.ReplyTo.AddRange(replyToAddrList); Enqueue(WrapMessage(m, user.Id)); } temp = templates.NewTicket; var subj = temp.ReplaceSubject(issue.Subject).ToString(); var body = temp.ReplaceBody(issue.Body, issue.Subject).Replace("#Numero_ticket#", $"{issue.Id}").ToString(); from = user.GetEmailAddress(); // notify all admins? if (notifs.NotifyAllAdmins ?? false) { var qry = _userRepo.All(q => q.NotDisabled().Admins().Not(user.Id).CanReceiveEmails()); await ForUsersAsync(qry, subj, body, from, replyToAddrList, cancellationToken); } // notify techs in their categories? if (notifs.NotifyTechs ?? false) { var qry = _userRepo.All(q => q.NotDisabled().Techs().Not(user.Id).CanReceiveEmails()); await ForUsersAsync(qry, subj, body, from, replyToAddrList, cancellationToken); } } break; case SysEventType.IssueAssigned: { // Notify ALL technicians in a category when another technician TAKES a ticket temp = await TemplateForUpdate($"{fullName} a pris en charge la résolution du ticket #{issue.Id}."); if (user.IsTech && (notifs.NotifyAllTechsOnTechTakeOver ?? false)) { await NotifyTechs(temp); } // notify ticket owner NotifyOwner(temp); } break; case SysEventType.IssueUpdated: { // Sent to both technicians and ticket-submitter (and all ticket-subscribers if any) when a new reply is added to the ticket temp = await TemplateForUpdate($"Le ticket #{issue.Id} a été mis à jour par {fullName}."); if (issue.UpdatedByUser) { from = user.GetEmailAddress(); var techsNotified = false; // Notify ALL technicians in a category when a customer updates a ticket // (not just the ticket-technician and ticket-subscribers)? if (issue.UpdatedForTechView || (notifs.NotifyAllTechsOnCustomerUpdate ?? false)) { await NotifyTechs(temp); techsNotified = true; } await NotifyAssignee(temp); // send to all subscribers but the submitter var qry = _subsRepo.All(q => q.QueryIssueSubscribers(issue.Id).But(user.Id)); if (techsNotified) { qry = qry.NotTechs(); // exclude the techs who've been notified previously } await ForSubscribersAsync(qry, temp.Subject, temp.Body, from, replyToAddrList, cancellationToken); } else { // send to submitter NotifyOwner(temp); // send to subscribers except the owner and updater var qry = _subsRepo.All(q => q.QueryIssueSubscribers(issue.Id).But(user.Id).But(issue.User.Id)); await ForSubscribersAsync(qry, temp.Subject, temp.Body, from, replyToAddrList, cancellationToken); } } break; case SysEventType.IssueClosed: { // Sent to subscribers when a ticket is closed. Note that "Ticket closed notifications" setting has to be on. if (notifs.TicketClosedNotification ?? false) { temp = await TemplateForUpdate($"Le ticket #{issue.Id} a été fermé par {fullName}."); NotifyOwner(temp); } } break; case SysEventType.IssueReopened: // no template for this scenario? break; case SysEventType.IssueDeleted: // no template for this scenario? break; default: // definitely no template for this scenario! break; } Consumer.Notify(); async Task <EmailTemplate> TemplateForUpdate(string whatHappened) { var comments = await _commentRepo.GetAsync(q => q.QueryCommentsForIssue(issue.Id).Skip(0).Take(3).ToArray()); var recent = string.Empty; if (comments.Length > 0) { try { recent = await _emailTemplatesViewRender.RenderToStringAsync(TEMPLATE_RECENT_COMMENTS, comments); } catch (Exception ex) { Logger.LogWarning(ex, "An error occured while rendering the recent comments e-mail template."); var sb = new StringBuilder("<h3>Messages récents</h3>"); foreach (var c in comments) { sb.AppendLine(); sb.AppendLine(c.Body); } recent = sb.ReplaceLineBreaks().ToString().Trim(); } } temp = templates.TicketUpdated; var subj = temp.ReplaceSubject(issue.Subject).ToString(); var body = temp .ReplaceBody(issue.Body, issue.Subject) .Replace("#Quoi_De_Neuf#", whatHappened) .Replace("#Messages_recents#", recent) .Replace("#Categorie#", issue.Category?.Name) .Replace("#Statut#", issue.Status?.Name) .Replace("#Priorite#", UtilExtensions.PriorityName(issue.Priority)) //.Replace("#What_Happened#", whatHappened) //.Replace("#Recent_messages#", recent) //.Replace("#Category#", catname) //.Replace("#Status#", statname) //.Replace("#Priority#", priority) .ToString(); return(new EmailTemplate { Body = body, Subject = subj }); } async Task NotifyTechs(EmailTemplate et) { var qry = _userRepo.All(q => q.NotDisabled().Techs().Not(user.Id).CanReceiveEmails()); await ForUsersAsync(qry, et.Subject, et.Body, from, replyToAddrList, cancellationToken); } async Task NotifyAssignee(EmailTemplate et) { if (issue.IsAssigned()) { var owner = await _userRepo.GetAsync(q => q.Find(issue.AssignedToUserId)); if (owner != null) { EnqueueTemplate(et, owner); } } } void NotifyOwner(EmailTemplate et) { var owner = issue.User; if (owner.SendEmail && owner.Id != user.Id) { EnqueueTemplate(et, owner); } } void SetFromName(AppUser u) { if (!useFromNameForAll) { from = user.GetEmailAddress(); } } void EnqueueTemplate(EmailTemplate et, AppUser owner) { SetFromName(owner); Enqueue(WrapMessage(CreateMessage(et.Subject, et.Body, from, owner.Email), owner.Id)); } } catch (Exception ex) { Logger.LogError(ex, $"Error while producing issue e-mails in {nameof(ProcessAsync)}."); } }
static void SendMailMime(MailInputs maildata) { try { //--------------------- // Configuration // User setup string User = maildata.User; string UserName = maildata.User; string pssw = maildata.Password; // Server setup string server = maildata.Server; int port = Convert.ToInt32(maildata.Port); // Mail setup string attachment = maildata.Attachment; string MailBody = maildata.Body; string MailSubject = maildata.Subject; string toAddressString = maildata.To; string ccAddressString = maildata.Cc; string bccAddressString = maildata.Bcc; //-------------------- MimeMessage message = new MimeMessage(); MailboxAddress from = new MailboxAddress(UserName, User); message.From.Add(from); if (!string.IsNullOrEmpty(toAddressString)) { InternetAddressList toList = new InternetAddressList(); toList.AddRange(MimeKit.InternetAddressList.Parse(toAddressString)); message.To.AddRange(toList); } if (!string.IsNullOrEmpty(ccAddressString)) { InternetAddressList ccList = new InternetAddressList(); ccList.AddRange(MimeKit.InternetAddressList.Parse(ccAddressString)); message.Cc.AddRange(ccList); } if (!string.IsNullOrEmpty(bccAddressString)) { InternetAddressList bccList = new InternetAddressList(); bccList.AddRange(MimeKit.InternetAddressList.Parse(bccAddressString)); message.Bcc.AddRange(bccList); } //Mail body BodyBuilder bodyBuilder = new BodyBuilder(); //bodyBuilder.HtmlBody = "<h1>This is a mail body</h1>"; message.Subject = MailSubject; if (!string.IsNullOrEmpty(MailBody)) { bodyBuilder.TextBody = MailBody; } // if (!string.IsNullOrEmpty(attachment)) { bodyBuilder.Attachments.Add(attachment); } message.Body = bodyBuilder.ToMessageBody(); SmtpClient client = new SmtpClient(); client.Connect(server, port, SecureSocketOptions.None); client.Authenticate(User, pssw); client.Send(message); client.Disconnect(true); client.Dispose(); Console.WriteLine(""); //Console.ReadLine(); //............................ } catch (Exception ep) { Console.WriteLine("failed to send email with the following error:"); Console.WriteLine(ep.Message); Console.ReadLine(); } }