-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
268 additions
and
32 deletions.
There are no files selected for viewing
15 changes: 15 additions & 0 deletions
15
Olive.Aws.Ses.AutoFetch.Tests/Olive.Aws.Ses.AutoFetch.Tests.csproj
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<TargetFramework>netcoreapp3.1</TargetFramework> | ||
|
||
<IsPackable>false</IsPackable> | ||
</PropertyGroup> | ||
|
||
<ItemGroup> | ||
<PackageReference Include="nunit" Version="3.12.0" /> | ||
<PackageReference Include="NUnit3TestAdapter" Version="3.15.1" /> | ||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0"/> | ||
</ItemGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using NUnit.Framework; | ||
|
||
namespace Olive.Aws.Ses.AutoFetch.Tests | ||
{ | ||
public class Tests | ||
{ | ||
[SetUp] | ||
public void Setup() | ||
{ | ||
} | ||
|
||
[Test] | ||
public void Test1() | ||
{ | ||
Assert.Pass(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,41 @@ | ||
using Amazon.SimpleEmail; | ||
using Amazon.SimpleEmail.Model; | ||
using Olive.Email; | ||
using Olive.Email; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Net.Mail; | ||
using System.Threading.Tasks; | ||
|
||
namespace Olive.Aws.Ses | ||
namespace Olive.Aws.Ses.AutoFetch | ||
{ | ||
public class AwsSesEmailDispatcher : IEmailDispatcher | ||
public class Mailbox | ||
{ | ||
public async Task Dispatch(MailMessage mail, IEmailMessage _) | ||
static List<EmailAccount> Accounts = new List<EmailAccount>(); | ||
public static void Watch(string emailS3Bucket) | ||
{ | ||
var request = CreateEmailRequest(mail); | ||
DatabaseTableService.EnsureDatabaseTable<MailMessage>(); | ||
Watch<MailMessage>(emailS3Bucket); | ||
} | ||
|
||
using (var client = new AmazonSimpleEmailServiceClient()) | ||
{ | ||
var response = await client.SendEmailAsync(request); | ||
if (response.HttpStatusCode != System.Net.HttpStatusCode.OK) | ||
throw new Exception("Failed to send an email: " + response.HttpStatusCode); | ||
} | ||
public static void Watch<TMailMessage>(string emailS3Bucket) where TMailMessage : IMailMessage, new() | ||
{ | ||
Accounts.Add(new EmailAccount<TMailMessage>(emailS3Bucket)); | ||
} | ||
|
||
SendEmailRequest CreateEmailRequest(MailMessage mail) | ||
public static async Task FetchAll() | ||
{ | ||
return new SendEmailRequest | ||
foreach (var account in Accounts) | ||
{ | ||
Source = mail.From.Address, | ||
Destination = new Destination | ||
try | ||
{ | ||
ToAddresses = mail.To.Select(t => t.Address).ToList() | ||
}, | ||
Message = new Message | ||
Log.For(typeof(Mailbox)).Info("Fetching emails for " + account.S3Bucket); | ||
await FetchClient.Fetch(account); | ||
Log.For(typeof(Mailbox)).Info("Fetched emails for " + account.S3Bucket); | ||
} | ||
catch (Exception ex) | ||
{ | ||
Subject = new Content(mail.Subject), | ||
Body = new Body | ||
{ | ||
Html = new Content | ||
{ | ||
Charset = "UTF-8", | ||
Data = mail.Body | ||
} | ||
} | ||
Log.For(typeof(Mailbox)).Error(ex); | ||
} | ||
}; | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace Olive.Aws.Ses.AutoFetch | ||
{ | ||
class DatabaseTableService | ||
{ | ||
const string CREATE_TABLE_COMMAND = @" | ||
if not exists (select * from sysobjects where name='MailMessages' and xtype='U') | ||
/****** Object: Table [dbo].[MailMessages] ******/ | ||
CREATE TABLE [dbo].[MailMessages]( | ||
[From] [nvarchar](1000) NOT NULL, | ||
[Subject] [nvarchar](1000) NOT NULL, | ||
[To] [nvarchar](1000) NOT NULL, | ||
[Bcc] [nvarchar](1000) NULL, | ||
[Cc] [nvarchar](1000) NULL, | ||
[Date] [datetime] NOT NULL, | ||
[Sender] [nvarchar](300) NULL, | ||
[Body] [nvarchar](max) NULL, | ||
) ON [PRIMARY] | ||
GO | ||
"; | ||
internal static Task EnsureDatabaseTable<T>() => Entities.Data.DataAccess.Create().ExecuteNonQuery(CREATE_TABLE_COMMAND); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
using MimeKit; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
|
||
namespace Olive.Aws.Ses.AutoFetch | ||
{ | ||
class EmailAccount | ||
{ | ||
public string S3Bucket { get; private set; } | ||
EmailAccount() | ||
{ | ||
|
||
} | ||
|
||
internal EmailAccount(string s3Bucket) | ||
{ | ||
S3Bucket = s3Bucket; | ||
} | ||
|
||
protected virtual IMailMessage CreateMailMessageInstance() => new MailMessage(); | ||
|
||
internal IMailMessage CreateMailMessage(MimeMessage message) | ||
{ | ||
var result = CreateMailMessageInstance(); | ||
|
||
result.From = message.From.Select(f => f.Name).ToString(","); | ||
result.To = message.To.Select(f => f.Name).ToString(","); | ||
result.HtmlBody = message.HtmlBody; | ||
result.Date = message.Date.DateTime; | ||
result.Sender = message.Sender.Name; | ||
result.Subject = message.Subject; | ||
|
||
|
||
return result; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace Olive.Aws.Ses.AutoFetch | ||
{ | ||
class EmailAccount<TMailMessage> : EmailAccount where TMailMessage : IMailMessage, new() | ||
{ | ||
internal EmailAccount(string s3Bucket) : base(s3Bucket) | ||
{ | ||
} | ||
|
||
internal override IMailMessage CreateMailMessageInstance() => new TMailMessage(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
using Olive.Entities.Data; | ||
using Olive; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Newtonsoft.Json; | ||
using MimeKit; | ||
using System.IO; | ||
|
||
namespace Olive.Aws.Ses.AutoFetch | ||
{ | ||
class FetchClient : IDisposable | ||
{ | ||
EmailAccount Account; | ||
Amazon.S3.AmazonS3Client S3Client; | ||
Database Database => Olive.Context.Current.Database(); | ||
FetchClient() | ||
{ | ||
S3Client = new Amazon.S3.AmazonS3Client(); | ||
} | ||
|
||
internal static async Task Fetch(EmailAccount account) | ||
{ | ||
using (var client = new FetchClient { Account = account }) | ||
await client.Fetch(); | ||
} | ||
|
||
void LogInfo(string log) => Log.For(this).Info(log); | ||
|
||
private async Task Fetch() | ||
{ | ||
var isEmpty = false; | ||
while (!isEmpty) | ||
{ | ||
LogInfo($"Downloading from " + Account.S3Bucket); | ||
var request = new Amazon.S3.Model.ListObjectsV2Request { BucketName = Account.S3Bucket }; | ||
var response = await S3Client.ListObjectsV2Async(request); | ||
|
||
LogInfo($"Downloaded {response.S3Objects.Count} items from " + Account.S3Bucket); | ||
|
||
foreach (var item in response.S3Objects) | ||
{ | ||
await Fetch(item); | ||
} | ||
|
||
Log.For(this).Info($"Downloaded {response.S3Objects.Count} items from " + Account.S3Bucket); | ||
|
||
isEmpty = response.NextContinuationToken.IsEmpty(); | ||
|
||
if (isEmpty) | ||
Log.For("Downloaded all the objects from " + Account.S3Bucket); | ||
} | ||
} | ||
|
||
async Task Fetch(Amazon.S3.Model.S3Object item) | ||
{ | ||
LogInfo("Downloading object " + item.Key); | ||
var message = await GetObject(item); | ||
LogInfo("Downloaded object " + item.Key); | ||
|
||
using (var scope = Database.CreateTransactionScope()) | ||
{ | ||
await Database.Save(message); | ||
|
||
LogInfo("Deleting object " + item.Key); | ||
await Delete(item); | ||
LogInfo("Deleted object " + item.Key); | ||
} | ||
|
||
} | ||
|
||
async Task<IMailMessage> GetObject(Amazon.S3.Model.S3Object item) | ||
{ | ||
var request = new Amazon.S3.Model.GetObjectRequest { Key = item.Key, BucketName = item.BucketName }; | ||
var response = await S3Client.GetObjectAsync(request); | ||
var sesMessage = MimeMessage.Load(response.ResponseStream); | ||
return Account.CreateMailMessage(sesMessage); | ||
} | ||
|
||
Task Delete(Amazon.S3.Model.S3Object item) | ||
{ | ||
var request = new Amazon.S3.Model.DeleteObjectRequest { BucketName = item.BucketName, Key = item.Key }; | ||
|
||
return S3Client.DeleteObjectAsync(request); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
S3Client?.Dispose(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using Olive.Entities; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace Olive.Aws.Ses.AutoFetch | ||
{ | ||
public interface IMailMessage : IEntity | ||
{ | ||
string From { get; set; } | ||
string To { get; set; } | ||
string Bcc { get; set; } | ||
string Cc { get; set; } | ||
string Subject { get; set; } | ||
string HtmlBody { get; set; } | ||
string Sender { get; set; } | ||
DateTime Date { get; set; } | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace Olive.Aws.Ses.AutoFetch | ||
{ | ||
class MailMessage : IMailMessage | ||
{ | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters