Skip to content

Commit c5c1a7d

Browse files
authored
Merge pull request #1594 from OctopusDeploy/mh/send-email-step
Add step template to support sending email via MailKit
2 parents 3bae710 + 29738e6 commit c5c1a7d

File tree

3 files changed

+150
-0
lines changed

3 files changed

+150
-0
lines changed

gulpfile.babel.js

+2
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,8 @@ function humanize(categoryId) {
145145
return "EdgeCast";
146146
case "elmah":
147147
return "ELMAH";
148+
case "email":
149+
return "Email";
148150
case "entityframework":
149151
return "Entity Framework";
150152
case "event-tracing":

step-templates/logos/email.png

9.78 KB
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
{
2+
"Id": "b163a315-24b7-4bf8-9cca-d9011f57019a",
3+
"Name": "Send Email using MailKit",
4+
"Description": "This step template supports sending an email using the [MailKit](https://github.com/jstedfast/MailKit) library, a cross-platform .NET library for IMAP, POP3, and SMTP.\n\n- Support for multiple TO addresses (separated by `,`).\n- Support for multiple CC addresses (separated by `,`).\n- *Optional* support for a separate `reply-to` address.\n\nThis step **does not** support running on PowerShell: Windows Desktop Edition.\n\n---\n\n**Required:** \n- The `MailKit` and `MimeKit` packages are installed on the target or worker. If the packages can't be found, the step will attempt to download them from [https://www.nuget.org](https://www.nuget.org).\n- PowerShell Core (including when running on Windows).\n\n*Notes:*\n\n- Tested on Octopus `2025.1`.\n- Tested on Windows and Linux with PowerShell Core only.",
5+
"ActionType": "Octopus.Script",
6+
"Version": 1,
7+
"CommunityActionTemplateId": null,
8+
"Packages": [],
9+
"GitDependencies": [],
10+
"Properties": {
11+
"Octopus.Action.PowerShell.Edition": "Core",
12+
"Octopus.Action.EnabledFeatures": "Octopus.Features.SelectPowerShellEditionForWindows",
13+
"Octopus.Action.Script.ScriptSource": "Inline",
14+
"Octopus.Action.Script.Syntax": "PowerShell",
15+
"Octopus.Action.Script.ScriptBody": "$ErrorActionPreference = \"Stop\";\n\nif ($PSEdition -eq \"Core\") {\n $PSStyle.OutputRendering = \"PlainText\"\n}\n$emailSubject = $OctopusParameters[\"SendEmail.Subject\"]\n$emailSmtpServer = $OctopusParameters[\"SendEmail.SmtpServer\"]\n$emailSmtpPort = $OctopusParameters[\"SendEmail.SmtpPort\"]\n$emailCredentialsUsername = $OctopusParameters[\"SendEmail.Credentials.Username\"]\n$emailCredentialsPassword = $OctopusParameters[\"SendEmail.Credentials.Password\"]\n$emailSecureSocketOption = $OctopusParameters[\"SendEmail.SecureSocketOption\"]\n\n$validSecureSocketOptions = @(\"None\", \"Auto\", \"SslOnConnect\", \"StartTls\", \"StartTlsWhenAvailable\")\nif(-not $validSecureSocketOptions.Contains($emailSecureSocketOption)) {\n Write-Error \"Invalid SecureSocketOption: $emailSecureSocketOption. Must be one of: $($validSecureSocketOptions -join \", \").\"\n return\n}\n\n$emailFromAddress = $OctopusParameters[\"SendEmail.FromAddress\"]\n$emailToAddresses = $OctopusParameters[\"SendEmail.TOAddresses\"]\n$emailCcAddresses = $OctopusParameters[\"SendEmail.CCAddresses\"]\n$emailReplyToAddress = $OctopusParameters[\"SendEmail.ReplyToAddress\"]\n\n$HtmlBody = $OctopusParameters[\"SendEmail.HtmlBody\"]\n$TextBody = $OctopusParameters[\"SendEmail.TextBody\"]\n\nWrite-Verbose \"Checking for MimeKit and MailKit packages.\"\ntry {\n \n $MimeKitPackage = (Get-Package MimeKit -ErrorAction Stop) | Select-Object -First 1\n} \ncatch {\n $MimeKitPackage = $null\n}\nif ($null -eq $MimeKitPackage) {\n Write-Output \"Downloading MimeKit from nuget.org.\"\n Install-Package -Name 'MimeKit' -Source \"https://www.nuget.org/api/v2\" -SkipDependencies -Force -Scope CurrentUser\n $MimeKitPackage = (Get-Package MimeKit) | Select-Object -First 1\n}\n\ntry {\n $MailKitPackage = (Get-Package MailKit -ErrorAction Stop) | Select-Object -First 1\n} \ncatch {\n $MailKitPackage = $null\n}\nif ($null -eq $MailKitPackage) {\n Write-Output \"Downloading MailKit from nuget.org.\"\n Install-Package -Name 'MailKit' -Source \"https://www.nuget.org/api/v2\" -SkipDependencies -Force -Scope CurrentUser\n $MailKitPackage = (Get-Package MailKit) | Select-Object -First 1\n}\n\n$MimeKitPath = Join-Path (Get-Item $MimeKitPackage.source).Directory.FullName \"lib/netstandard2.1/MimeKit.dll\"\n$MailKitPath = Join-Path (Get-Item $MailKitPackage.source).Directory.FullName \"lib/netstandard2.1/MailKit.dll\"\n\nAdd-Type -Path $MimeKitPath\nAdd-Type -Path $MailKitPath\n\n# Validation/Setting of Secure Socket Options needed after libraries loaded\nswitch($emailSecureSocketOption) {\n \"Auto\" {\n $secureSocketOption = [MailKit.Security.SecureSocketOptions]::Auto\n }\n \"None\" {\n $secureSocketOption = [MailKit.Security.SecureSocketOptions]::None\n }\n \"SslOnConnect\" {\n $secureSocketOption = [MailKit.Security.SecureSocketOptions]::SslOnConnect\n }\n \"StartTls\" {\n $secureSocketOption = [MailKit.Security.SecureSocketOptions]::StartTls\n }\n \"StartTlsWhenAvailable\" {\n $secureSocketOption = [MailKit.Security.SecureSocketOptions]::StartTlsWhenAvailable\n }\n default {\n Write-Error \"Invalid SecureSocketOption: $emailSecureSocketOption. Must be one of: $($validSecureSocketOptions -join \", \").\"\n return\n }\n}\n\n$SMTP = New-Object MailKit.Net.Smtp.SmtpClient\n\n$Message = New-Object MimeKit.MimeMessage\n$ContentBuilder = [MimeKit.BodyBuilder]::new()\n\n$ContentBuilder.HtmlBody = $HtmlBody\n$ContentBuilder.TextBody = $TextBody\nWrite-Verbose \"Setting From address: $emailFromAddress\" \n$Message.From.Add($emailFromAddress)\n$toAddresses = $emailToAddresses -split \",\"\nWrite-Verbose \"Setting TO addresses: $emailToAddresses\"\nforeach($toAddress in $toAddresses) {\n $Message.To.Add($toAddress)\n}\n\nif(-not [string]::IsNullOrWhitespace($emailCcAddresses)) {\n Write-Verbose \"Setting CC addresses: $emailCcAddresses\"\n $ccAddresses = $emailCcAddresses -split \",\"\n foreach($ccAddress in $ccAddresses) {\n $Message.Cc.Add($ccAddress)\n }\n}\nif(-not [string]::IsNullOrWhitespace($emailReplyToAddress)) {\n Write-Verbose \"Setting ReplyTo address: $emailReplyToAddress\"\n $Message.ReplyTo.Add($emailReplyToAddress)\n}\n\nWrite-Verbose \"Setting subject to: $emailSubject\"\n$Message.Subject = $emailSubject\nWrite-Verbose \"Setting MimeMessage Body contents\"\n$Message.Body = $ContentBuilder.ToMessageBody()\nWrite-Verbose \"Connecting to SMTP server: $emailSmtpServer on port: $emailSmtpPort (using SecureSocketOption=$emailSecureSocketOption)\"\n$SMTP.Connect($emailSmtpServer, $emailSmtpPort, $secureSocketOption)\nWrite-Verbose \"Authenticating...\"\n$SMTP.Authenticate($emailCredentialsUsername, $emailCredentialsPassword)\nWrite-Output \"Sending email...\"\n$SMTP.Send($Message)\nWrite-Output \"Email sent.\"\n$SMTP.Disconnect($true)\n$SMTP.Dispose()"
16+
},
17+
"Parameters": [
18+
{
19+
"Id": "65b67843-2cd5-48a5-ac9d-611de16246a7",
20+
"Name": "SendEmail.SmtpServer",
21+
"Label": "SMTP Server",
22+
"HelpText": "The SMTP Server address e.g. `smtp.gmail.com`",
23+
"DefaultValue": "",
24+
"DisplaySettings": {
25+
"Octopus.ControlType": "SingleLineText"
26+
}
27+
},
28+
{
29+
"Id": "3d87558e-aa18-46af-85bb-644890d6654b",
30+
"Name": "SendEmail.SmtpPort",
31+
"Label": "SMTP Port",
32+
"HelpText": "The SMTP Port used for connecting. Typical SMTP ports are: \n- `25`\n- `587` (STARTTLS)\n- `465` (SSL)",
33+
"DefaultValue": "",
34+
"DisplaySettings": {
35+
"Octopus.ControlType": "SingleLineText"
36+
}
37+
},
38+
{
39+
"Id": "0c1f7ae0-8cd4-45a5-b53b-e5019ad5ecb0",
40+
"Name": "SendEmail.SecureSocketOption",
41+
"Label": "SSL Option",
42+
"HelpText": "The [SSL Option](https://mimekit.net/docs/html/T_MailKit_Security_SecureSocketOptions.htm) to use:\n- `None`: No SSL or TLS encryption should be used\n- `Auto`: Allow the [IMailService](https://mimekit.net/docs/html/T_MailKit_IMailService.htm) to decide which SSL or TLS options to use (default). If the server does not support SSL or TLS, then the connection will continue without any encryption.\n- `SslOnConnect`: The connection should use SSL or TLS encryption immediately.\n- `StartTls`: Elevates the connection to use TLS encryption immediately after reading the greeting and capabilities of the server. If the server does not support the STARTTLS extension, then the connection will fail and a NotSupportedException will be thrown.\n- `StartTlsWhenAvailable`: Elevates the connection to use TLS encryption immediately after reading the greeting and capabilities of the server, but only if the server supports the STARTTLS extension.\n\nDefault: `Auto`.",
43+
"DefaultValue": "Auto",
44+
"DisplaySettings": {
45+
"Octopus.ControlType": "Select",
46+
"Octopus.SelectOptions": "None|None\nAuto|Auto\nSslOnConnect|Use SSL\nStartTls|Use STARTTLS\nStartTlsWhenAvailable|Start Tls When Available"
47+
}
48+
},
49+
{
50+
"Id": "208a3bab-b331-4fa6-a122-459593a4c98f",
51+
"Name": "SendEmail.Credentials.Username",
52+
"Label": "Authentication Username",
53+
"HelpText": "The username to authenticate with the SMTP Server.",
54+
"DefaultValue": "",
55+
"DisplaySettings": {
56+
"Octopus.ControlType": "Sensitive"
57+
}
58+
},
59+
{
60+
"Id": "d42aba20-174a-4b51-af88-78d332f09a08",
61+
"Name": "SendEmail.Credentials.Password",
62+
"Label": "Authentication Password",
63+
"HelpText": "The password to authenticate with the SMTP Server.",
64+
"DefaultValue": "",
65+
"DisplaySettings": {
66+
"Octopus.ControlType": "Sensitive"
67+
}
68+
},
69+
{
70+
"Id": "8eafb51b-599b-4c51-8d35-974c5843c9cb",
71+
"Name": "SendEmail.Subject",
72+
"Label": "Email Subject",
73+
"HelpText": "The Email Subject",
74+
"DefaultValue": "",
75+
"DisplaySettings": {
76+
"Octopus.ControlType": "SingleLineText"
77+
}
78+
},
79+
{
80+
"Id": "bc4d18f8-e096-4911-84ce-e35268c83934",
81+
"Name": "SendEmail.FromAddress",
82+
"Label": "From Address",
83+
"HelpText": "The sender address of the Email",
84+
"DefaultValue": "",
85+
"DisplaySettings": {
86+
"Octopus.ControlType": "SingleLineText"
87+
}
88+
},
89+
{
90+
"Id": "302fb573-5720-47b6-bbd7-7d0077ca75ba",
91+
"Name": "SendEmail.TOAddresses",
92+
"Label": "TO addresses",
93+
"HelpText": "The recipients of the Email. Multiple addresses can be supplied, separated by a `,`.",
94+
"DefaultValue": "",
95+
"DisplaySettings": {
96+
"Octopus.ControlType": "SingleLineText"
97+
}
98+
},
99+
{
100+
"Id": "be2267f6-36b0-4f7e-a7cf-f274e56aff2f",
101+
"Name": "SendEmail.CCAddresses",
102+
"Label": "(Optional) CC addresses",
103+
"HelpText": "The *optional* CC (carbon-copy) recipients of the Email. Multiple addresses can be supplied, separated by a `,`.",
104+
"DefaultValue": "",
105+
"DisplaySettings": {
106+
"Octopus.ControlType": "SingleLineText"
107+
}
108+
},
109+
{
110+
"Id": "b43c49fd-3214-4310-a8cf-10489a3c858f",
111+
"Name": "SendEmail.ReplyToAddress",
112+
"Label": "(Optional) Reply-to address",
113+
"HelpText": "The *optional* `reply-to` address.",
114+
"DefaultValue": "",
115+
"DisplaySettings": {
116+
"Octopus.ControlType": "SingleLineText"
117+
}
118+
},
119+
{
120+
"Id": "9e07a17f-a044-4f6f-ac0c-5d131058a270",
121+
"Name": "SendEmail.HtmlBody",
122+
"Label": "HTML Message Body",
123+
"HelpText": "The HTML message body of the Email.",
124+
"DefaultValue": "",
125+
"DisplaySettings": {
126+
"Octopus.ControlType": "MultiLineText"
127+
}
128+
},
129+
{
130+
"Id": "bd111434-193d-413b-9d7e-279381061a0c",
131+
"Name": "SendEmail.TextBody",
132+
"Label": "Plain Text Message Body",
133+
"HelpText": "The Text message body of the Email.",
134+
"DefaultValue": "",
135+
"DisplaySettings": {
136+
"Octopus.ControlType": "MultiLineText"
137+
}
138+
}
139+
],
140+
"StepPackageId": "Octopus.Script",
141+
"$Meta": {
142+
"ExportedAt": "2025-02-26T14:52:39.564Z",
143+
"OctopusVersion": "2025.2.937",
144+
"Type": "ActionTemplate"
145+
},
146+
"LastModifiedBy": "harrisonmeister",
147+
"Category": "email"
148+
}

0 commit comments

Comments
 (0)