/// <summary> /// Sends one pending delivery item with the specified identifier. /// </summary> /// <param name="id">The delivery item identifier.</param> /// <param name="autoCloseConnection"> /// If set to <c>true</c> will close connection immediately after delivering the message. /// If caller is sending multiple messages, optionally set to false to leave the mail service connection open. /// </param> /// <param name="token">The cancellation token.</param> /// <returns>Task<IEnumerable<MessageDeliveryItem>>.</returns> public virtual async Task <DeliveryItem> SendAsync( Guid id, bool autoCloseConnection = true, CancellationToken token = new CancellationToken()) { using (await _deliverablesLock.LockAsync()) { var deliveryItem = ((IMailer)this).PendingDeliverables.FirstOrDefault(d => d.Id == id); if (deliveryItem != null) { try { deliveryItem.ProviderMessageId = await DeliverMessageAsync(deliveryItem, autoCloseConnection, token); deliveryItem.IsSuccess = true; Logger.LogInformation( "Mailer delivery {result} for delivery item '{deliveryItemId}' sent to '{to}' with subject '{subject}'", deliveryItem.IsSuccess ? "success" : "failure", deliveryItem.Id, deliveryItem.ToEmailAddress, deliveryItem.Subject ); } catch (Exception ex) { Logger.LogError(1, ex, "Mailer delivery {result} for delivery item '{deliveryItemId}' with exception '{exceptionMessage}'", "error", id, ex.Message); deliveryItem.ExceptionMessage = $"{ex.Message}\n\n{ex.StackTrace}"; } finally { try { await HistoryStore.AddAsync(deliveryItem, token); } catch (Exception ex) { //do not re-throw, record that history fail and allow sendAll to continue delivering other items. Logger.LogError(1, ex, "History store add {result} for delivery item '{deliveryItemId}' with exception '{exceptionMessage}'", "error", id, ex.Message); } PendingDeliveryItems.Remove(deliveryItem); } } return(deliveryItem); } }
/// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public virtual void Dispose() { var unsent = PendingDeliveryItems.Where(m => !m.IsSuccess && string.IsNullOrEmpty(m.ExceptionMessage)) .ToArray(); if (unsent.Any()) { var b = new StringBuilder(); b.AppendLine("Mailer instance disposed with {numMessages} undelivered messages"); b.AppendLine("Instance type '{mailerType}'"); b.AppendLine("Undelivered Messages:"); foreach (var u in unsent) { b.AppendLine($" Delivery item ID '{u.Id}' to '{u.ToEmailAddress}' with subject '{u.Subject}'"); } Logger.LogWarning(b.ToString(), unsent.Count(), GetType().Name); } ((IMailer)this).PendingDeliverables = null; }