![]() |
VOOZH | about |
dotnet add package Cosmos.EmailServices --version 9.0.1
NuGet\Install-Package Cosmos.EmailServices -Version 9.0.1
<PackageReference Include="Cosmos.EmailServices" Version="9.0.1" />
<PackageVersion Include="Cosmos.EmailServices" Version="9.0.1" />Directory.Packages.props
<PackageReference Include="Cosmos.EmailServices" />Project file
paket add Cosmos.EmailServices --version 9.0.1
#r "nuget: Cosmos.EmailServices, 9.0.1"
#:package Cosmos.EmailServices@9.0.1
#addin nuget:?package=Cosmos.EmailServices&version=9.0.1Install as a Cake Addin
#tool nuget:?package=Cosmos.EmailServices&version=9.0.1Install as a Cake Tool
This is an IEmailSender implementation for Cosmos CMS and for use with any ASP.NET Core Identity web app. Instructions for setting up each of these email services are provided in this documentation.
In one package it provides the following services:
To install the package using CLI, run the following command:
dotnet add package Cosmos.EmailServices
To install the package using NuGet Package Manager, run the following command:
Install-Package Cosmos.EmailServices
In the user secrets of an ASP.NET Core Identity web app, add one of the following configuration depending on the service you want to use.
To configure for Azure Communication services, add the following configuration to the user secrets:
{
"AdminEmail": "your@emailaddress.com", // This is the default 'from to address',
"ConnectionStrings": {
{
"AzureCommunicationConnection" : "[Your connection string here]"
}
}
To configure for SendGrid, add the following configuration:
{
"AdminEmail": "your@emailaddress.com", // This is the default 'from to address',
"CosmosSendGridApiKey": "[Your SendGrid key here]",
}
To configure for an SMTP service, add the following configuration:
{
"AdminEmail": "", // This is the default 'from to address',
"SmtpEmailProviderOptions" : {
"Host": "smtp.yourhost.com",
"Port": 587,
"UsesSsl": true, // False if uses TLS
"UserName": "yourusername",
"Password": "yourpassword"
}
}
If none of the three settings above are given, this will install a NoOp email service.
ConfigureServices method of Startup.csAdd the following using:
using Cosmos.EmailServices;
Then add the following line:
builder.Services.AddCosmosEmailServices(builder.Configuration);
For a full working example of this package, see the Cosmos CMS source code.
In the mean time, here is an example of how to use the email service in a Razor Page:
// <copyright file="ResetPassword.cshtml.cs" company="Moonrise Software, LLC">
// Copyright (c) Moonrise Software, LLC. All rights reserved.
// Licensed under the GNU Public License, Version 3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
// See https://github.com/MoonriseSoftwareCalifornia/CosmosCMS
// for more information concerning the license and the contributors participating to this project.
// </copyright>
namespace Cosmos.Cms.Areas.Identity.Pages.Account
{
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cosmos.Cms.Common.Services.Configurations;
using Cosmos.Common.Data;
using Cosmos.EmailServices;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.RateLimiting;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
/// <summary>
/// Reset password page model.
/// </summary>
[AllowAnonymous]
[EnableRateLimiting("fixed")]
public class ResetPasswordModel : PageModel
{
private readonly IOptions<SiteSettings> options;
private readonly ICosmosEmailSender emailSender;
private readonly ApplicationDbContext dbContext;
private readonly ILogger<ForgotPasswordModel> logger;
private readonly UserManager<IdentityUser> userManager;
/// <summary>
/// Initializes a new instance of the <see cref="ResetPasswordModel"/> class.
/// </summary>
/// <param name="userManager">User manager.</param>
/// <param name="options">Site settings.</param>
/// <param name="emailSender">Email sender service.</param>
/// <param name="dbContext">Database context.</param>
/// <param name="logger">Log service.</param>
public ResetPasswordModel(
UserManager<IdentityUser> userManager,
IOptions<SiteSettings> options,
IEmailSender emailSender,
ApplicationDbContext dbContext,
ILogger<ForgotPasswordModel> logger)
{
this.userManager = userManager;
this.options = options;
this.emailSender = (ICosmosEmailSender)emailSender;
this.dbContext = dbContext;
this.logger = logger;
}
/// <summary>
/// Gets or sets input model.
/// </summary>
[BindProperty]
public InputModel Input { get; set; }
/// <summary>
/// Get handler.
/// </summary>
/// <param name="code">Reset password verification code.</param>
/// <returns>Returns an <see cref="IActionResult"/>.</returns>
public IActionResult OnGet(string code = null)
{
if (code == null)
{
return BadRequest("A code must be supplied for password reset.");
}
Input = new InputModel
{
Code = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(code))
};
return Page();
}
/// <summary>
/// Post handler.
/// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
var homePage = await dbContext.Pages.Select(s => new { s.Title, s.UrlPath }).FirstOrDefaultAsync(f => f.UrlPath == "root");
var websiteName = homePage.Title ?? Request.Host.Host;
var admins = await userManager.GetUsersInRoleAsync("Administrators");
var emailHandler = new EmailHandler(emailSender, logger);
var user = await userManager.FindByEmailAsync(Input.Email);
if (user == null)
{
await emailHandler.SendGeneralInfoTemplateEmail(
"User without an account tried to change a password",
"System Notification",
websiteName,
Request.Host.Host,
$"<p>This is a notification that '{Input.Email},' who does not have an account on this website, tried to change a password for website '{Request.Host.Host}' on {DateTime.UtcNow.ToString()} (UTC). No password reset email was sent.</p>",
admins.Select(s => s.Email).ToList());
// Don't reveal that the user does not exist
return RedirectToPage("./ResetPasswordConfirmation");
}
var result = await userManager.ResetPasswordAsync(user, Input.Code, Input.Password);
if (result.Succeeded)
{
// Notify the administrators of a password change.
await emailHandler.SendGeneralInfoTemplateEmail(
"Password was changed.",
"System Notification",
websiteName,
Request.Host.Host,
$"<p>This is a notification that '{Input.Email}' changed their password for website '{Request.Host.Host}' on {DateTime.UtcNow.ToString()} (UTC).</p>",
admins.Select(s => s.Email).ToList());
// Notify the user of a password change.
await emailHandler.SendGeneralInfoTemplateEmail(
"Password was changed.",
"System Notification",
websiteName,
Request.Host.Host,
$"<p>This is a confirmation that your password was changed for website '{Request.Host.Host}' on {DateTime.UtcNow.ToString()} (UTC).</p>",
Input.Email);
return RedirectToPage("./ResetPasswordConfirmation");
}
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
return Page();
}
/// <summary>
/// Form input model.
/// </summary>
public class InputModel
{
/// <summary>
/// Gets or sets user email address.
/// </summary>
[Required]
[EmailAddress]
public string Email { get; set; }
/// <summary>
/// Gets or sets error message (if any).
/// </summary>
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
[DataType(DataType.Password)]
public string Password { get; set; }
/// <summary>
/// Gets or sets confirm password field.
/// </summary>
[DataType(DataType.Password)]
[Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
/// <summary>
/// Gets or sets code field.
/// </summary>
public string Code { get; set; }
}
}
}
This package comes with a few Email templates that can be used to format emails.
Each template consists of two files. One for HTML formatted email and another for text.
Here are examples of two files found in the 'Templates' folder:
GeneralInfo.html GeneralInfoTXT.txt
Here is an example of the text file:
{{Subject}}
{{Subtitle}}
From: {{WebsiteName}}
{{Body}}
Note the double brackes. This are spots in the email where content is inserted.
If you add templates to this project, please add them to the EmailTemplates.resx
file.
Here is an example of how to use the general email templates in the code:
await emailHandler.SendGeneralInfoTemplateEmail(
"Password was changed.",
"System Notification",
websiteName,
Request.Host.Host,
$"<p>This is a confirmation that your password was changed for website '{Request.Host.Host}' on {DateTime.UtcNow.ToString()} (UTC).</p>",
Input.Email);
For more options, see class EmailHandler.cs.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 net9.0 is compatible. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 was computed. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
Showing the top 1 NuGet packages that depend on Cosmos.EmailServices:
| Package | Downloads |
|---|---|
|
Cosmos.Common
This package contains all the common methods and objects used by the Cosmos CMS editor website, and by any website service the role of a publishing website. |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 9.0.1 | 1,972 | 1/20/2025 |
| 9.0.0.5 | 458 | 1/15/2025 |
| 8.1.0.1 | 390 | 1/7/2025 |
| 8.0.11.31 | 420 | 11/21/2024 |
| 8.0.10.28 | 436 | 11/14/2024 |
| 8.0.10.26 | 404 | 11/13/2024 |
| 8.0.10.24 | 411 | 11/7/2024 |
| 8.0.10.20 | 419 | 11/1/2024 |
| 8.0.10.18 | 419 | 10/29/2024 |
| 8.0.10.12 | 421 | 10/25/2024 |
| 8.0.10.4 | 389 | 10/16/2024 |
| 8.0.8.1 | 388 | 10/2/2024 |
| 8.0.7.7 | 381 | 10/1/2024 |
| 8.0.6.6 | 401 | 9/7/2024 |
| 8.0.6.2 | 404 | 8/27/2024 |
| 8.0.4.13 | 423 | 4/18/2024 |
| 8.0.4.12 | 403 | 3/29/2024 |
| 8.0.3.1 | 489 | 1/5/2024 |
| 8.0.0.3 | 442 | 12/18/2023 |
Documentation dependencies updated.