public async Task <bool> TrySendSingleMailAsync( IMailReference mail, StreamWriter writer, StreamReader reader, CancellationToken token) { _log.Information($"Sending mail {mail.Id}"); IMailReadReference readMail = await _queue.OpenReadAsync(mail, token); _log.Information($"Sender: {readMail.Sender}, Recipients: {string.Join(",", readMail.Recipients)}"); SmtpResponse response = await ExecuteRemoteCommandAsync(writer, reader, $"MAIL FROM:<{readMail.Sender}>"); if (response.Code != SmtpReplyCode.Okay) { _log.Warning("Failed MAIL FROM, aborting"); return(false); } foreach (string recipient in readMail.Recipients) { response = await ExecuteRemoteCommandAsync(writer, reader, $"RCPT TO:<{recipient}>"); if (response.Code != SmtpReplyCode.Okay) { _log.Warning("Failed RCPT TO, aborting"); return(false); } } response = await ExecuteRemoteCommandAsync(writer, reader, "DATA"); if (response.Code != SmtpReplyCode.StartMail) { _log.Warning("Failed DATA, aborting"); return(false); } using (var mailReader = new StreamReader(readMail.BodyStream)) { string line = null; while (await mailReader.TryReadLineAsync(l => line = l, token)) { await writer.WriteLineAsync(line); } } await writer.WriteLineAsync("."); response = await ReadResponseAsync(reader); if (response.Code != SmtpReplyCode.Okay) { _log.Warning("Failed RCPT TO, aborting"); return(false); } await _queue.DeleteAsync(mail); return(true); }
public Task DeleteAsync(IMailReference reference) { var mockReference = (MockMailReference)reference; References.Remove(mockReference); DeletedReferences.Add(mockReference); return(Task.CompletedTask); }
public Task DeleteAsync(IMailReference reference) { var mailReference = reference as IReference; if (mailReference != null && File.Exists(mailReference.Path)) { File.Delete(mailReference.Path); } return(Task.FromResult((object)null)); }
public SmtpFailureData ShouldAttemptRedelivery(IMailReference mail) { SmtpFailureData failure = _failures.GetFailure(mail.Id, true); if (failure.Retries + 1 >= s_retryDelays.Length) { return(null); } return(failure); }
public virtual Task DeleteAsync(IMailReference reference) { if (reference is IReference mailReference) { if (File.Exists(mailReference.Path)) { File.Delete(mailReference.Path); } } return(Task.CompletedTask); }
/// <summary> /// use this method for template-driven email messages /// </summary> /// <param name="sender"></param> /// <param name="recipients"></param> /// <param name="mailReference"></param> public void BuildEmailMessage(string sender, IList <string> recipients, IMailReference mailReference) { try { IMail email = _composer.Compose(sender, recipients, mailReference); _client.SendEmail(email); } catch (Exception) { throw; } }
public IMail Compose(string sender, IList <string> recipients, IMailReference mailReference) { // build email message // get email template string emailTemplate = _templateFactory.GetEmailTemplateMessage(mailReference.MessageType); // replace markers from email template Dictionary <string, string> dictMarkers = mailReference.MapObjectDictionary(); foreach (var item in dictMarkers) { emailTemplate = emailTemplate.Replace("##" + item.Key + "##", item.Value); } return(new Mail(sender, recipients, mailReference.EmailSubject, emailTemplate, mailReference.ContentType)); }
public override async Task DeleteAsync(IMailReference reference) { await base.DeleteAsync(reference); try { // var mailReference = (Reference) reference; // root/in/domain.name/cur/mail-id-path.mbx // we want to remove the domain.name directory if this is the last mail going into it // Directory.Delete(Path.GetDirectoryName(Path.GetDirectoryName(mailReference.Path))); } catch (Exception) { // Don't care, we were just cleaning up after ourselves, after all } }
public async Task <IMailReadReference> OpenReadAsync(IMailReference reference) { var mailReference = reference as IReference; if (mailReference == null) { throw new ArgumentNullException(nameof(reference)); } using (var stream = Sharable.Create(File.OpenRead(mailReference.Path))) { string sender; List <string> recipients = new List <string>(); using (var reader = new StreamReader(stream.Peek(), Encoding.UTF8, false, 1024, true)) { var fromLine = await reader.ReadLineAsync(); if (!fromLine.StartsWith("FROM:")) { throw new FormatException("Invalid mail file format, expected FROM line"); } sender = fromLine.Substring(5); while (true) { var line = await reader.ReadLineAsync(); if (line.StartsWith("---")) { break; } if (line.StartsWith("TO:")) { recipients.Add(line.Substring(3)); continue; } throw new FormatException("Invalid mail file format, expected TO: line or Begin Message"); } } return(new ReadReference(sender, recipients, mailReference.Path, stream.TakeValue())); } }
public bool IsReadyToSend(IMailReference mail) { SmtpFailureData failure = _failures.GetFailure(mail.Id, false); if (failure == null) { return(true); } TimeSpan currentLag = DateTimeOffset.UtcNow - failure.FirstFailure; if (currentLag < CalculateNextRetryInterval(failure.Retries)) { return(false); } return(true); }
public Task <IMailReadReference> OpenReadAsync(IMailReference reference, CancellationToken token) { return(Task.FromResult((IMailReadReference)reference)); }
public async Task <IMailReadReference> OpenReadAsync(IMailReference reference, CancellationToken token) { var mailReference = reference as Reference; if (mailReference == null) { throw new ArgumentNullException(nameof(reference)); } using (Sharable <FileStream> stream = Sharable.Create(File.OpenRead(mailReference.Path))) { string sender; var recipients = new List <string>(); FileStream streamImpl = stream.Peek(); // 23 ASCII characters, up to 1 GB in size, should be sufficient // Header-Legnth:000000000 string headerSizeHeader = Encoding.ASCII.GetString(await streamImpl.ReadExactlyAsync(23, token)); if (!headerSizeHeader.StartsWith(HeaderLengthHeader)) { throw new FormatException($"Invalid mail file format, expected {HeaderLengthHeader} line"); } if (!int.TryParse(headerSizeHeader.Substring(HeaderLengthHeader.Length), out int headerSize) || headerSize <= 0) { throw new FormatException($"Invalid mail file format, {HeaderLengthHeader} is not a valid number"); } using (var reader = new StreamReader(new StreamSpan(streamImpl, 0, headerSize), Encoding.UTF8, false, 1, true)) { // This should be the "new line" at the end of the Header-Length we've already consumed // so all that is left is the rest of the line (which is empty). // If it's not, then we didn't read what we thought we read, bail string blankLine = await reader.ReadLineAsync(); if (!string.IsNullOrEmpty(blankLine)) { throw new FormatException($"Invalid mail file format, {HeaderLengthHeader} is improperly formatted"); } string fromLine = await reader.ReadLineAsync(); if (!fromLine.StartsWith("FROM:")) { throw new FormatException("Invalid mail file format, expected FROM line"); } sender = fromLine.Substring(5); string line = null; while (await reader.TryReadLineAsync(l => line = l, token)) { if (line.StartsWith("TO:")) { recipients.Add(line.Substring(3)); continue; } throw new FormatException("Invalid mail file format, expected TO: line or Begin Message"); } } return(new ReadReference( mailReference.Id, sender, recipients, mailReference.Path, new StreamSpan(stream.TakeValue()), this)); } }
private Task HandleRejectedMailAsync(IMailReference mail) { _log.Warning($"Max reties attempted for mail {mail.Id}, deleting"); return(Task.CompletedTask); }