Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch SendGrid Email Notification to AWS SnS #191

Merged
merged 10 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion NotificationSystem/NotificationSystem.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AWSSDK.SimpleEmail" Version="3.7.401.11" />
<PackageReference Include="Azure.Storage.Queues" Version="12.11.1" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.CosmosDB" Version="3.0.10" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.SendGrid" Version="3.0.2" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="4.0.5" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.3" />
<PackageReference Include="RateLimiter" Version="2.2.0" />
<PackageReference Include="System.Net.NameResolution" Version="4.3.0" />
<PackageReference Include="Microsoft.Azure.WebJobs" Version="3.0.33" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions" Version="4.0.1" />
Expand Down
8 changes: 4 additions & 4 deletions NotificationSystem/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,15 @@ In the moderators flow:

- A change in the Cosmos DB metadata store triggers the SendModeratorEmail function
- If there is a newly detected orca call that requires a moderator to validate, the function fetches the relevant email list
- The function then calls SendGrid to send emails to moderators
- The function then calls AWS Simple Email Service to send emails to moderators
dyuvaraaj marked this conversation as resolved.
Show resolved Hide resolved

In the subscribers flow:

- A change in the Cosmos DB metadata store triggers the DbToQueue function
- If there is a new orca call that the moderator has validated, the function sends a message to a queue
- The SendSubscriberEmail function periodically checks the queue
- If there are items in the queue, the function fetches the relevant email list
- The function then calls SendGrid to send emails to subscribers
- The function then calls AWS Simple Email Service to send emails to subscribers

## Get email list

Expand Down Expand Up @@ -111,7 +111,6 @@ All resources are located in resource group **LiveSRKWNotificationSystem**.
1. Storage account with queues, email template images and moderator/subscriber list: orcanotificationstorage
2. Metadata store (from which some functions are triggered): aifororcasmetadatastore
3. Azure function app: orcanotification
4. SendGrid account (for sending emails): aifororcas

## Run Locally
It is recommended to go to the "orcanotification" function app, then Settings > Configuration to find the app settings used.
Expand All @@ -127,7 +126,8 @@ Create local.settings.json in the current directory (NotificationSystem) using t

"OrcaNotificationStorageSetting": "<storage account connection string>",
"aifororcasmetadatastore_DOCUMENTDB": "<cosmos db connection string>",
"SendGridKey": "<SendGrid API key>",
"AWS_ACCESS_KEY_ID": "<AWS Access Key>",
"AWS_SECRET_ACCESS_KEY": "<AWS Secret Key>",
dyuvaraaj marked this conversation as resolved.
Show resolved Hide resolved
"SenderEmail": "<email address>"
}
}
Expand Down
16 changes: 11 additions & 5 deletions NotificationSystem/SendModeratorEmail.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
using System;
using Amazon;
using Amazon.SimpleEmail;
using RateLimiter;
using ComposableAsync;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Azure.Cosmos.Table;
Expand All @@ -7,13 +11,14 @@
using Microsoft.Extensions.Logging;
using NotificationSystem.Template;
using NotificationSystem.Utilities;
using SendGrid.Helpers.Mail;

namespace NotificationSystem
{
[StorageAccount("OrcaNotificationStorageSetting")]
public static class SendModeratorEmail
{
static int SendRate = 14;

[FunctionName("SendModeratorEmail")]
public static async Task Run(
[CosmosDBTrigger(
Expand All @@ -24,7 +29,6 @@ public static async Task Run(
LeaseCollectionPrefix = "moderator",
CreateLeaseCollectionIfNotExists = true)]IReadOnlyList<Document> input,
[Table("EmailList")] CloudTable cloudTable,
[SendGrid(ApiKey = "SendGridKey")] IAsyncCollector<SendGridMessage> messageCollector,
ILogger log)
{
if (input == null || input.Count == 0)
Expand Down Expand Up @@ -54,16 +58,18 @@ public static async Task Run(
return;
}

// TODO: make better email
string body = EmailTemplate.GetModeratorEmailBody(documentTimeStamp, location);

var timeConstraint = TimeLimiter.GetFromMaxCountByInterval(SendRate, TimeSpan.FromSeconds(1));
var aws = new AmazonSimpleEmailServiceClient(RegionEndpoint.USWest2);
log.LogInformation("Retrieving email list and sending notifications");
foreach (var emailEntity in EmailHelpers.GetEmailEntities(cloudTable, "Moderator"))
{
string emailSubject = string.Format("OrcaHello Candidate at location {0}", location);
await timeConstraint;
string emailSubject = string.Format("OrcaHello Candidate at location {0}", location);
var email = EmailHelpers.CreateEmail(Environment.GetEnvironmentVariable("SenderEmail"),
emailEntity.Email, emailSubject, body);
await messageCollector.AddAsync(email);
await aws.SendEmailAsync(email);
}
}
}
Expand Down
13 changes: 10 additions & 3 deletions NotificationSystem/SendSubscriberEmail.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
using System;
using Amazon;
using Amazon.SimpleEmail;
using RateLimiter;
using ComposableAsync;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
Expand All @@ -10,20 +14,20 @@
using Newtonsoft.Json.Linq;
using NotificationSystem.Template;
using NotificationSystem.Utilities;
using SendGrid.Helpers.Mail;

namespace NotificationSystem
{
[StorageAccount("OrcaNotificationStorageSetting")]
public static class SendSubscriberEmail
{
static int SendRate = 14;

[FunctionName("SendSubscriberEmail")]
// TODO: change timer to once per hour (0 0 * * * *)
public static async Task Run(
[TimerTrigger("0 */1 * * * *")] TimerInfo myTimer,
[Queue("srkwfound")] CloudQueue cloudQueue,
[Table("EmailList")] CloudTable cloudTable,
[SendGrid(ApiKey = "SendGridKey")] IAsyncCollector<SendGridMessage> messageCollector,
ILogger log)
{
log.LogInformation("Checking if there are items in queue");
Expand All @@ -38,12 +42,15 @@ public static async Task Run(
log.LogInformation("Creating email message");
var body = await CreateBody(cloudQueue);

var timeConstraint = TimeLimiter.GetFromMaxCountByInterval(SendRate, TimeSpan.FromSeconds(1));
var aws = new AmazonSimpleEmailServiceClient(RegionEndpoint.USWest2);
log.LogInformation("Retrieving email list and sending notifications");
foreach (var emailEntity in EmailHelpers.GetEmailEntities(cloudTable, "Subscriber"))
{
await timeConstraint;
var email = EmailHelpers.CreateEmail(Environment.GetEnvironmentVariable("SenderEmail"),
emailEntity.Email, "Notification: Orca detected!", body);
await messageCollector.AddAsync(email);
await aws.SendEmailAsync(email);
}
}

Expand Down
24 changes: 16 additions & 8 deletions NotificationSystem/Utilities/EmailHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using NotificationSystem.Models;
using SendGrid.Helpers.Mail;
using Amazon.SimpleEmail.Model;

namespace NotificationSystem.Utilities
{
Expand Down Expand Up @@ -72,14 +72,22 @@ public static IEnumerable<EmailEntity> GetEmailEntities(CloudTable cloudTable, s
return cloudTable.ExecuteQuery(query);
}

public static SendGridMessage CreateEmail(string from, string to, string subject, string body)
public static SendEmailRequest CreateEmail(string from, string to, string subject, string body)
{
var message = new SendGridMessage();
message.AddTo(to);
message.AddContent("text/html", body);
message.SetFrom(from);
message.SetSubject(subject);
return message;
var email = new SendEmailRequest();
email.Source = from;
email.Destination = new Destination(new List<string> { to });
//Create message and attach to email request.
dyuvaraaj marked this conversation as resolved.
Show resolved Hide resolved
Message message = new Message();
message.Subject = new Content(subject);
message.Body = new Body();
message.Body.Html = new Content
{
Charset = "UTF-8",
Data = body
};
email.Message = message;
return email;
}
}
}
Loading