diff --git a/README.md b/README.md index 78ecfe4..d73e8a4 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ This repository provides examples demonstrating how to use Oracle Functions. | Run a SQL statement against Autonomous DB using ORDS | [sample](./samples/oci-adb-ords-runsql-python) ||[sample](./samples/oci-adb-ords-runsql-dotnet)| | Run a SQL statement against Autonomous DB using DB Client |[sample](./samples/oci-adb-client-runsql-python)|| [sample](./samples/oci-adb-client-runsql-dotnet)| | Publish a notification using ONS |[sample](./samples/oci-ons-publish-python)||[sample](./samples/oci-ons-publish-dotnet)| -| Send an email using Email Delivery Service |[sample](./samples/oci-email-send-python)| +| Send an email using Email Delivery Service |[sample](./samples/oci-email-send-python)||[sample](./samples/oci-email-send-python)| | Decrypt cipher using Vault keys |[sample](./samples/oci-vault-decrypt-python)||[sample](./samples/oci-vault-decrypt-dotnet)| | Get a secret from Vault |[sample](./samples/oci-vault-get-secret-python)||[sample](./samples/oci-vault-get-secret-dotnet)| | Write IAM policies that enables Functions in a tenancy to access resources in other tenancies ||[sample](./samples/oci-cross-tenancy-policies-java) diff --git a/samples/oci-email-send-dotnet/Dockerfile b/samples/oci-email-send-dotnet/Dockerfile new file mode 100644 index 0000000..7c1e978 --- /dev/null +++ b/samples/oci-email-send-dotnet/Dockerfile @@ -0,0 +1,11 @@ +FROM fnproject/dotnet:3.1-1.0.4-dev as build-stage +WORKDIR /function +COPY . . +RUN dotnet sln add SendEmail.csproj +RUN dotnet build SendEmail.csproj -c Release +RUN dotnet publish SendEmail.csproj -c Release -o out +FROM fnproject/dotnet:3.1-1.0.4 +WORKDIR /function +COPY --from=build-stage /function/out/ /function/ +ENTRYPOINT ["dotnet", "SendEmail.dll"] +CMD ["SendEmail:Function:function_handler"] \ No newline at end of file diff --git a/samples/oci-email-send-dotnet/Function.sln b/samples/oci-email-send-dotnet/Function.sln new file mode 100644 index 0000000..f87916a --- /dev/null +++ b/samples/oci-email-send-dotnet/Function.sln @@ -0,0 +1,17 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.26124.0 +MinimumVisualStudioVersion = 15.0.26124.0 +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/samples/oci-email-send-dotnet/Models/InputMessage.cs b/samples/oci-email-send-dotnet/Models/InputMessage.cs new file mode 100644 index 0000000..366a5d2 --- /dev/null +++ b/samples/oci-email-send-dotnet/Models/InputMessage.cs @@ -0,0 +1,17 @@ +using System; + +namespace SendEmail +{ + + class InputMessage + { + public string sender_email { get; set; } + public string sender_name { get; set; } + public string recipient { get; set; } + public string subject { get; set; } + public string body { get; set; } + + + } + +} diff --git a/samples/oci-email-send-dotnet/Models/Output.cs b/samples/oci-email-send-dotnet/Models/Output.cs new file mode 100644 index 0000000..fc7035a --- /dev/null +++ b/samples/oci-email-send-dotnet/Models/Output.cs @@ -0,0 +1,17 @@ +using System; + +namespace SendEmail +{ + + class Output + { + public string message + { + get; + set; + } + + public Output(string message) { this.message = message; } + } + +} diff --git a/samples/oci-email-send-dotnet/README.md b/samples/oci-email-send-dotnet/README.md new file mode 100644 index 0000000..92f84e8 --- /dev/null +++ b/samples/oci-email-send-dotnet/README.md @@ -0,0 +1,107 @@ +# Function that sends an email using OCI Email Delivery +This function sends an email using the OCI Email Delivery Service. + +As you make your way through this tutorial, look out for this icon ![user input icon](./images/userinput.png). +Whenever you see it, it's time for you to perform an action. + + +## Prerequisites +Before you deploy this sample function, make sure you have run step A, B and C of the [Oracle Functions Quick Start Guide for Cloud Shell](https://www.oracle.com/webfolder/technetwork/tutorials/infographics/oci_functions_cloudshell_quickview/functions_quickview_top/functions_quickview/index.html) +* A - Set up your tenancy +* B - Create application +* C - Set up your Cloud Shell dev environment + + +## List Applications +Assuming your have successfully completed the prerequisites, you should see your +application in the list of applications. +``` +fn ls apps +``` + + +## Review and customize the function +Review the following files in the current folder: +* the code of the function, [SendEmail.cs](./SendEmail.cs) +* its dependencies, [SendEmail.csproj](./SendEmail.csproj) +* the function metadata, [func.yaml](./func.yaml) + + +## Deploy the function +In Cloud Shell, run the *fn deploy* command to build the function and its dependencies as a Docker image, +push the image to OCIR, and deploy the function to Oracle Functions in your application. + +![user input icon](./images/userinput.png) +``` +fn -v deploy --app +``` + + +## Configure the Email Delivery Service +![user input icon](./images/userinput.png) + +On the OCI console, navigate to *Email Delivery*. Click `Create Approved Sender`. +![create topic](./images/create_approved_sender-1.png) + +Enter the email address of the approved sender and click `Create Approved Sender`. + +![create subscription](./images/create_approved_sender-2.png) + +The creation of the *Approved Sender* takes several minutes. + +Navigate to *Email Delivery* > *Email Configuration* and write down the SMTP server name. +Click `Manage SMTP Credentials` which takes you to your *User Details*, click on `Generate SMTP Credentials` and enter a description. Your SMTP Username and password will be displayed, write them down, you will need them to configure the function. + + +## Set the function configuration values +The function requires the following configuration values to be set: +- smtp-username +- smtp-password +- smtp-host +- smtp-port (25 or 587) + +![user input icon](./images/userinput.png) + +Use the *fn CLI* to set the config value: +``` +fn config function smtp-username +fn config function smtp-password +fn config function smtp-host +fn config function smtp-port +``` +e.g. +``` +fn config function myapp oci-email-send-dotnet smtp-username "ocid1.user.oc1..aaaaaaaause3s2zw3kn3qvxxc5c5ouc4pu6byfxiuplncjkzzxinijhmqj5q@ocid1.tenancy.oc1..aaaaaaaaydrjm77otncda2xn7qtv7l3hqnd3zxn2u6siwdhniibwfv4wwhta.7g.com" +fn config function myapp oci-email-send-dotnet smtp-password '{$M$mWmvlN&P#o>!14F8' +fn config function myapp oci-email-send-dotnet smtp-host "smtp.us-phoenix-1.oraclecloud.com" +fn config function myapp oci-email-send-dotnet smtp-port 587 +``` + + +## Invoke the function +The function requires the following keys in the payload to be invoked: +- sender_email +- sender_name +- recipient +- subject +- body + +![user input icon](./images/userinput.png) +``` +echo '{ "sender_email":"", "sender_name":"", "recipient":"", +"subject":"", "body":"" }' | fn invoke oci-email-send-dotnet +``` +e.g.: +``` +echo '{ "sender_email":"no-reply@oracle.com", "sender-name":"Test", "recipient":"abc@xyz.com", +"subject":"Hello!", "body":"This is a test email" }' | fn invoke myapp oci-email-send-dotnet +``` + +Upon success, the function will return "Email successfully sent!" and the recipient will receive an email. + + +## Monitoring Functions + +Learn how to configure basic observability for your function using metrics, alarms and email alerts: +* [Basic Guidance for Monitoring your Functions](../basic-observability/functions.md) + diff --git a/samples/oci-email-send-dotnet/SendEmail.cs b/samples/oci-email-send-dotnet/SendEmail.cs new file mode 100644 index 0000000..15bebe3 --- /dev/null +++ b/samples/oci-email-send-dotnet/SendEmail.cs @@ -0,0 +1,67 @@ +using Fnproject.Fn.Fdk; +using System.Runtime.CompilerServices; +using System.Collections.Generic; +using System; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +using MailKit.Net.Smtp; +using MailKit.Security; +using MailKit; +using MimeKit; + +namespace SendEmail +{ + class Function + { + public Output function_handler(InputMessage input) + { + + string smtp_password = Environment.GetEnvironmentVariable("smtp-password"); + string smtp_user_name = Environment.GetEnvironmentVariable("smtp-username"); + string smtp_endpoint = Environment.GetEnvironmentVariable("smtp-host"); + string smtp_port_str = Environment.GetEnvironmentVariable("smtp-port"); + int smtp_port = Int32.Parse(smtp_port_str); + string from_email = input.sender_email; + string from_name = input.sender_name; + + var message = new MimeMessage(); + message.From.Add(new MailboxAddress(from_name, from_email)); + message.To.Add(new MailboxAddress("Dear recipient", input.recipient)); + message.Subject = input.subject; + + message.Body = new TextPart("plain") + { + Text = @input.body + }; + + try + { + + + using (var client = new SmtpClient()) + { + client.Connect(smtp_endpoint, smtp_port, SecureSocketOptions.StartTls); + client.Authenticate(smtp_user_name, smtp_password); + client.Send(message); + client.Disconnect(true); + } + + return new Output(string.Format( + "Mail Sent to {0}!", + string.IsNullOrEmpty(input.recipient) ? "" : input.recipient.Trim())); + + } + catch (Exception ex) + { + Console.WriteLine("Error: " + ex.Message); + return new Output(string.Format(ex.Message)); + + } + + } + + static void Main(string[] args) { Fdk.Handle(args[0]); } + + } +} diff --git a/samples/oci-email-send-dotnet/SendEmail.csproj b/samples/oci-email-send-dotnet/SendEmail.csproj new file mode 100644 index 0000000..0a33e1a --- /dev/null +++ b/samples/oci-email-send-dotnet/SendEmail.csproj @@ -0,0 +1,18 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + + + + diff --git a/samples/oci-email-send-dotnet/func.yaml b/samples/oci-email-send-dotnet/func.yaml new file mode 100644 index 0000000..18e5fb7 --- /dev/null +++ b/samples/oci-email-send-dotnet/func.yaml @@ -0,0 +1,8 @@ +schema_version: 20180708 +name: oci-email-send-dotnet +version: 0.0.107 +runtime: dotnet3.1 +build_image: fnproject/dotnet:3.1-1.0.4-dev +run_image: fnproject/dotnet:3.1-1.0.4 +cmd: SendEmail:Function:function_handler +entrypoint: dotnet SendEmail.dll diff --git a/samples/oci-email-send-dotnet/images/create_approved_sender-1.png b/samples/oci-email-send-dotnet/images/create_approved_sender-1.png new file mode 100644 index 0000000..1588283 Binary files /dev/null and b/samples/oci-email-send-dotnet/images/create_approved_sender-1.png differ diff --git a/samples/oci-email-send-dotnet/images/create_approved_sender-2.png b/samples/oci-email-send-dotnet/images/create_approved_sender-2.png new file mode 100644 index 0000000..eb2b9f1 Binary files /dev/null and b/samples/oci-email-send-dotnet/images/create_approved_sender-2.png differ diff --git a/samples/oci-email-send-dotnet/images/userinput.png b/samples/oci-email-send-dotnet/images/userinput.png new file mode 100644 index 0000000..ce6a202 Binary files /dev/null and b/samples/oci-email-send-dotnet/images/userinput.png differ