Skip to content

Commit

Permalink
Bug fixes for #63, part 1
Browse files Browse the repository at this point in the history
  • Loading branch information
danzuep committed Jun 19, 2024
1 parent 256569b commit 9b2ad4e
Show file tree
Hide file tree
Showing 12 changed files with 159 additions and 62 deletions.
2 changes: 1 addition & 1 deletion samples/EmailWpfApp/EmailWpfApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
<PackageReference Include="CommunityToolkit.Diagnostics" Version="8.2.2" />
<PackageReference Include="CommunityToolkit.Common" Version="8.2.2" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.4" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.6" />
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="8.0.0" />
Expand Down
94 changes: 64 additions & 30 deletions samples/WorkerServiceExample/Worker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,16 @@ namespace ExampleNamespace;

public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly ISmtpSender _smtpSender;
private readonly IImapReceiver _imapReceiver;
private readonly IServiceScope _serviceScope;
private readonly ILoggerFactory _loggerFactory;
private readonly ILogger<Worker> _logger;

public Worker(IServiceScopeFactory serviceScopeFactory, ISmtpSender smtpSender, IImapReceiver imapReceiver, ILoggerFactory loggerFactory)
public Worker(IServiceScopeFactory serviceScopeFactory, ILoggerFactory loggerFactory)
{
_serviceScope = serviceScopeFactory.CreateScope();
_imapReceiver = _serviceScope.ServiceProvider.GetRequiredService<IImapReceiver>();
_logger = loggerFactory.CreateLogger<Worker>();
_serviceScopeFactory = serviceScopeFactory;
_smtpSender = smtpSender;
_imapReceiver = imapReceiver;
_loggerFactory = loggerFactory;
}

Expand All @@ -43,7 +41,9 @@ protected override async Task ExecuteAsync(CancellationToken cancellationToken =
//await ImapReceiverFactoryAsync(cancellationToken);
//await MailFolderMonitorFactoryAsync(cancellationToken);
//await GetMessageSummaryRepliesAsync(cancellationToken);
await GetMimeMessageRepliesAsync(cancellationToken);
//await GetMimeMessageRepliesAsync(cancellationToken);
//await AddFlagsToNewestMessageSummaryAsync(cancellationToken);
await GetMailFolderCacheAsync();
}

private static ImapReceiver CreateExchangeOAuth2ImapClientExample(SaslMechanismOAuth2 oauth2)
Expand All @@ -56,8 +56,7 @@ private static ImapReceiver CreateExchangeOAuth2ImapClientExample(SaslMechanismO

private async Task ImapReceiverFactoryAsync(CancellationToken cancellationToken = default)
{
using var scope = _serviceScopeFactory.CreateScope();
var imapReceiverFactory = scope.ServiceProvider.GetRequiredService<IImapReceiverFactory>();
var imapReceiverFactory = _serviceScope.ServiceProvider.GetRequiredService<IImapReceiverFactory>();
var receivers = imapReceiverFactory.GetAllImapReceivers();
foreach (var receiver in receivers)
{
Expand All @@ -70,18 +69,16 @@ private async Task ImapReceiverFactoryAsync(CancellationToken cancellationToken

private async Task MailFolderMonitorFactoryAsync(CancellationToken cancellationToken = default)
{
using var scope = _serviceScopeFactory.CreateScope();
var mailFolderMonitorFactory = scope.ServiceProvider.GetRequiredService<IMailFolderMonitorFactory>();
var mailFolderMonitorFactory = _serviceScope.ServiceProvider.GetRequiredService<IMailFolderMonitorFactory>();
void LogUniqueIdArrived(IMessageSummary messageSummary) =>
_logger.LogInformation($"Message #{messageSummary.UniqueId} arrived.");
await mailFolderMonitorFactory.MonitorAllMailboxesAsync(LogUniqueIdArrived, cancellationToken);
}

private async Task MailFolderMonitorMoveFolderAsync(string destinationFolderFullName, CancellationToken cancellationToken = default)
{
using var scope = _serviceScopeFactory.CreateScope();
var mailFolderClient = scope.ServiceProvider.GetRequiredService<IMailFolderClient>();
var mailFolderMonitorFactory = scope.ServiceProvider.GetRequiredService<IMailFolderMonitorFactory>();
using var mailFolderClient = _serviceScope.ServiceProvider.GetRequiredService<IMailFolderClient>();
var mailFolderMonitorFactory = _serviceScope.ServiceProvider.GetRequiredService<IMailFolderMonitorFactory>();
async Task UniqueIdArrivedAsync(IMessageSummary messageSummary) =>
await mailFolderClient.MoveToAsync(messageSummary, destinationFolderFullName, cancellationToken);
await mailFolderMonitorFactory.MonitorAllMailboxesAsync(UniqueIdArrivedAsync, cancellationToken);
Expand Down Expand Up @@ -119,18 +116,34 @@ private async Task MoveSeenToSentAsync(CancellationTokenSource cancellationToken

private async Task AddToDraftFolderAsync()
{
var mimeMessage = CreateTemplate().MimeMessage;
using var smtpSender = _serviceScope.ServiceProvider.GetRequiredService<ISmtpSender>();
var mimeMessage = CreateTemplate(smtpSender).MimeMessage;
var draftsFolder = _imapReceiver.MailFolderClient.DraftsFolder;
var uniqueId = await draftsFolder.AppendAsync(mimeMessage);
_logger.LogInformation($"Added mime message to {_imapReceiver} {draftsFolder.FullName} folder as #{uniqueId}.");
}

private async Task MoveTopOneToFolderAsync(string destinationFolderName = "INBOX/Processed", CancellationToken cancellationToken = default)
private async Task MoveTopOneToFolderAsync(IMailFolderClient mailFolderClient, string destinationFolderFullName, CancellationToken cancellationToken = default)
{
var destinationFolder = await _imapReceiver.MailFolderClient.GetFolderAsync([destinationFolderName], cancellationToken);
var messageSummary = await GetTopMessageSummaryAsync(cancellationToken);
var uniqueId = await messageSummary.MoveToAsync(destinationFolder, cancellationToken);
_logger.LogInformation($"Added mime message to {_imapReceiver} {destinationFolder.FullName} folder as #{uniqueId}.");
var uniqueId = await mailFolderClient.MoveToAsync(messageSummary, destinationFolderFullName, cancellationToken);
//var destinationFolder = await mailFolderClient.GetFolderAsync([destinationFolderFullName], cancellationToken);
//var uniqueId = await messageSummary.MoveToAsync(destinationFolder, cancellationToken);
_logger.LogInformation($"Added mime message to {_imapReceiver} {destinationFolderFullName} folder as #{uniqueId}.");
}

private async Task CreateFolderAndMoveTopOneAsync(string destinationFolderFullName = "INBOX/Processed", CancellationToken cancellationToken = default)
{
using var mailFolderClient = _serviceScope.ServiceProvider.GetRequiredService<IMailFolderClient>();
var folder = await mailFolderClient.GetOrCreateFolderAsync(destinationFolderFullName, cancellationToken);
await MoveTopOneToFolderAsync(mailFolderClient, destinationFolderFullName, cancellationToken);
}

private async Task GetMailFolderCacheAsync(string destinationFolderFullName = "INBOX", CancellationToken cancellationToken = default)
{
var mailFolderCache = _serviceScope.ServiceProvider.GetRequiredService<IMailFolderCache>();
var folder = await mailFolderCache.GetMailFolderAsync(_imapReceiver, destinationFolderFullName, createIfMissing: true, cancellationToken);
_logger.LogInformation(folder?.FullName);
}

public async Task GetMailFolderAsync(string mailFolderName, CancellationToken cancellationToken = default)
Expand Down Expand Up @@ -203,15 +216,16 @@ private async Task ForwardFirstEmailAsync(CancellationToken cancellationToken =

private async Task ForwardMessageSummaryAsync(IMessageSummary messageSummary, CancellationToken cancellationToken = default)
{
using var smtpSender = _serviceScope.ServiceProvider.GetRequiredService<ISmtpSender>();
var mimeForward = await messageSummary.GetForwardMessageAsync(
"<p>FYI.</p>", includeMessageId: true, cancellationToken);
mimeForward.From.Add("[email protected]");
mimeForward.To.Add("[email protected]");
_logger.LogInformation($"{_imapReceiver} reply: \r\n{mimeForward.HtmlBody}");
await _smtpSender.SendAsync(mimeForward, cancellationToken);
await smtpSender.SendAsync(mimeForward, cancellationToken);
await _imapReceiver.MailFolderClient.SentFolder.AppendAsync(mimeForward);
//await _imapReceiver.MailFolderClient.MoveToAsync(messageSummary, SpecialFolder.Sent, cancellationToken);
//_smtpSender.Enqueue(mimeForward);
//smtpSender.Enqueue(mimeForward);
}

public async Task<MimeMessage?> GetNewestMimeMessageAsync(CancellationToken cancellationToken = default)
Expand All @@ -222,6 +236,15 @@ private async Task ForwardMessageSummaryAsync(IMessageSummary messageSummary, Ca
return mimeMessage;
}

public async Task<int?> AddFlagsToNewestMessageSummaryAsync(CancellationToken cancellationToken = default)
{
using var mailFolderClient = _imapReceiver.MailFolderClient;
var messageSummary = await GetNewestMessageSummaryAsync(mailFolderClient, cancellationToken);
if (messageSummary == null) return null;
var uniqueId = await mailFolderClient.AddFlagsAsync([messageSummary.UniqueId], MessageFlags.Seen);
return uniqueId;
}

public async Task<IMessageSummary?> GetNewestMessageSummaryAsync(IMailFolderClient? mailFolderClient = null, CancellationToken cancellationToken = default)
{
bool dispose = mailFolderClient == null;
Expand All @@ -239,6 +262,7 @@ private async Task ForwardMessageSummaryAsync(IMessageSummary messageSummary, Ca

private async Task GetMessageSummaryRepliesAsync(CancellationToken cancellationToken = default)
{
//using var smtpSender = _serviceScope.ServiceProvider.GetRequiredService<ISmtpSender>();
var stopwatch = Stopwatch.StartNew();
var messageSummaries = await _imapReceiver.ReadMail
.Skip(0).Take(1).ItemsForMimeMessages()
Expand All @@ -254,12 +278,13 @@ private async Task GetMessageSummaryRepliesAsync(CancellationToken cancellationT
mimeReply.From.Add("from@localhost");
mimeReply.To.Add("to@localhost");
_logger.LogInformation($"{_imapReceiver} reply: \r\n{mimeReply.HtmlBody}");
//await _smtpSender.SendAsync(mimeReply, cancellationToken);
//await smtpSender.SendAsync(mimeReply, cancellationToken);
}
}

private async Task GetMimeMessageRepliesAsync(CancellationToken cancellationToken = default)
{
//using var smtpSender = _serviceScope.ServiceProvider.GetRequiredService<ISmtpSender>();
var stopwatch = Stopwatch.StartNew();
var mimeMessages = await _imapReceiver.ReadMail.Top(1)
.GetMimeMessagesEnvelopeBodyAsync(cancellationToken);
Expand All @@ -272,7 +297,7 @@ private async Task GetMimeMessageRepliesAsync(CancellationToken cancellationToke
.From("from@localhost")
.To("to@localhost");
_logger.LogInformation($"{_imapReceiver} reply: \r\n{mimeReply.HtmlBody}");
//await _smtpSender.SendAsync(mimeReply);
//await smtpSender.SendAsync(mimeReply);
}
}

Expand Down Expand Up @@ -382,12 +407,12 @@ private async Task QueryAsync(CancellationToken cancellationToken = default)
_logger.LogInformation($"{_imapReceiver} received {messageSummaries.Count} email(s) in {stopwatch.Elapsed.TotalSeconds:n1}s: {messageSummaries.Select(m => m.UniqueId).ToEnumeratedString()}.");
}

private IEmailWriter CreateTemplate(string from = "[email protected]")
private IEmailWriter CreateTemplate(ISmtpSender smtpSender, string from = "[email protected]")
{
if (!from.IsEmail())
_logger.LogWarning($"{from} is not a valid email.");
var id = $"{Guid.NewGuid():N}"[..8];
var template = _smtpSender.WriteEmail
var template = smtpSender.WriteEmail
.From(from)
.To($"{id}@localhost")
.Subject(id)
Expand All @@ -399,9 +424,10 @@ private IEmailWriter CreateTemplate(string from = "[email protected]")

private async Task TemplateSendAsync(byte numberToSend = 1, CancellationToken cancellationToken = default)
{
using var smtpSender = _serviceScope.ServiceProvider.GetRequiredService<ISmtpSender>();
//var template = await GetTemplate().SaveTemplateAsync();
//var template = await _smtpSender.WithTemplateAsync();
var template = CreateTemplate();
//var template = await smtpSender.WithTemplateAsync();
var template = CreateTemplate(smtpSender);
int count = 0;
do
{
Expand All @@ -414,7 +440,8 @@ private async Task TemplateSendAsync(byte numberToSend = 1, CancellationToken ca

private async Task SendAttachmentAsync(int millisecondsDelay, string filePath = "..\\..\\README.md", CancellationToken cancellationToken = default)
{
bool isSent = await CreateTemplate()
using var smtpSender = _serviceScope.ServiceProvider.GetRequiredService<ISmtpSender>();
bool isSent = await CreateTemplate(smtpSender)
.TryAttach(filePath)
.TrySendAsync(cancellationToken);
_logger.LogInformation($"Email {(isSent ? "sent" : "failed to send")}.");
Expand All @@ -423,8 +450,9 @@ private async Task SendAttachmentAsync(int millisecondsDelay, string filePath =

private async Task DelayedSendAsync(int millisecondsDelay, CancellationToken cancellationToken = default)
{
using var smtpSender = _serviceScope.ServiceProvider.GetRequiredService<ISmtpSender>();
await Task.Delay(millisecondsDelay, cancellationToken);
bool isSent = await CreateTemplate().TrySendAsync(cancellationToken);
bool isSent = await CreateTemplate(smtpSender).TrySendAsync(cancellationToken);
_logger.LogInformation($"Email {(isSent ? "sent" : "failed to send")}.");
}

Expand All @@ -439,4 +467,10 @@ await _imapReceiver.MonitorFolder
.IdleAsync(cancellationToken);
await sendTask;
}

public override void Dispose()
{
_serviceScope.Dispose();
base.Dispose();
}
}
4 changes: 2 additions & 2 deletions source/MailKitSimplified.Email/MailKitSimplified.Email.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@
<PackageReference Include="CommunityToolkit.Diagnostics" Version="8.2.2" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.2" />
<PackageReference Include="MailKitSimplified.Generic" Version="2.0.0" />
<PackageReference Include="MailKitSimplified.Sender" Version="2.9.0" />
<PackageReference Include="MailKitSimplified.Receiver" Version="2.9.0" />
<PackageReference Include="MailKitSimplified.Sender" Version="2.10.0" />
<PackageReference Include="MailKitSimplified.Receiver" Version="2.10.0" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ namespace MailKitSimplified.Receiver.Services
{
public interface IMailFolderCache
{
Task<IMailFolder> GetMailFolderAsync(IImapReceiver imapReceiver, string mailFolderFullName, CancellationToken cancellationToken = default);
Task<IMailFolder> GetMailFolderAsync(IImapReceiver imapReceiver, string mailFolderFullName, bool createIfMissing = false, CancellationToken cancellationToken = default);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ internal static async IAsyncEnumerable<IMailFolder> GetAllSubfoldersAsync(this I
{
if (imapClient == null)
throw new ArgumentNullException(nameof(imapClient));
if (!imapClient.IsConnected)
throw new ServiceNotConnectedException(nameof(imapClient));
foreach (var folderNamespace in imapClient.PersonalNamespaces)
{
await foreach (var folder in imapClient.GetAllSubfoldersAsync(folderNamespace).WithCancellation(cancellationToken).ConfigureAwait(false))
Expand Down Expand Up @@ -82,6 +84,8 @@ internal static async Task<IList<IMailFolder>> GetAllSubfoldersAsync(this IImapC
{
if (imapClient == null)
throw new ArgumentNullException(nameof(imapClient));
if (!imapClient.IsConnected)
throw new ServiceNotConnectedException(nameof(imapClient));
var results = new List<IMailFolder>();
foreach (var folderNamespace in imapClient.PersonalNamespaces)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,8 @@ internal static string QuoteForReply(this MimeMessage original, string message,
string GetHtml(InternetAddressList contacts) => contacts.Mailboxes.Select(a => $"\"{a.Name}\" &lt;{a.Address}&gt;").ToEnumeratedString("; ");
stringBuilder.AppendLine("<div>");
stringBuilder.AppendLine(message ?? string.Empty);
stringBuilder.AppendLine("</div><br /><blockquote><hr /><div>");
stringBuilder.AppendLine("</div><br />");
stringBuilder.AppendLine("<blockquote><hr /><div>");
if (includeMessageId)
stringBuilder.AppendLine($"<b>Message-ID:</b> &lt;{original.MessageId}&gt;<br />");
stringBuilder.AppendLine($"<b>Sent:</b> {original.Date}<br />");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
</ItemGroup>

<ItemGroup>
<PackageReference Update="MailKit" Version="4.5.0" />
<PackageReference Update="MimeKit" Version="4.5.0" />
<PackageReference Update="MailKit" Version="4.6.0" />
<PackageReference Update="MimeKit" Version="4.6.0" />
</ItemGroup>

</Project>
Loading

0 comments on commit 9b2ad4e

Please sign in to comment.