Asp.Net 核心创建一个控制器来使用 SendGrid 发送电子邮件

Asp.Net Core create a controller to send emails using SendGrid

我正在尝试按照这个 https://www.ryadel.com/en/asp-net-core-send-email-messages-sendgrid-api/ 教程

创建一个控制器

我已经添加了除控制器之外的所有内容。我在控制器中的代码是这样的

public class SendGridController : BaseApiController
{
    private readonly IEmailSender _emailSender;
    public SendGridController(IEmailSender emailSender)
    {
        _emailSender = emailSender;
        
    }

    [HttpPost]
    [ProducesResponseType(typeof(string), (int)HttpStatusCode.OK)]
    [ProducesResponseType(typeof(string), (int)HttpStatusCode.BadRequest)]
    [ProducesResponseType((int)HttpStatusCode.Unauthorized)]
    [ProducesResponseType(typeof(string), (int)HttpStatusCode.InternalServerError)]
    public async Task<ActionResult> SendEmail() {
        await _emailSender.SendEmailAsync("test@mail.com", "subject", "something");
        return Ok(await _emailSender.SendEmailAsync("test@mail.com", "subject", "something"));
    }
}

但我收到以下错误

Argument 1: cannot convert from 'void' to 'object'

我希望能够看到来自发送网格的响应,无论它是否已发送。

这是 SendGridEmailSender class:

public class SendGridEmailSender : IEmailSender
{
    public SendGridEmailSender(
        IOptions<SendGridEmailSenderOptions> options
        )
    {
        this.Options = options.Value;
    }

    public SendGridEmailSenderOptions Options { get; set; }

    public async Task SendEmailAsync(
        string email, 
        string subject, 
        string message)
    {
        await Execute(Options.ApiKey, subject, message, email);
    }

    private async Task<Response> Execute(
        string apiKey, 
        string subject, 
        string message, 
        string email)
    {
        var client = new SendGridClient(apiKey);
        var msg = new SendGridMessage()
        {
            From = new EmailAddress(Options.SenderEmail, Options.SenderName),
            Subject = subject,
            PlainTextContent = message,
            HtmlContent = message
        };
        msg.AddTo(new EmailAddress(email));

        // disable tracking settings
        // ref.: https://sendgrid.com/docs/User_Guide/Settings/tracking.html
        msg.SetClickTracking(false, false);
        msg.SetOpenTracking(false);
        msg.SetGoogleAnalytics(false);
        msg.SetSubscriptionTracking(false);

        return await client.SendEmailAsync(msg);
    }
}

您没有 returning 您拥有的 private 方法的结果:

await Execute(Options.ApiKey, subject, message, email);

所以,你需要return结果

public async Task SendEmailAsync(
    string email, 
    string subject, 
    string message)
{
    result = await Execute(Options.ApiKey, subject, message, email);
    // do some checks with result
}

如果您需要在您的控制器代码中检查结果,这将更加棘手,因为 IEmailSender 的签名不提供通用任务对象,您需要手动将其转换 (不推荐)。您可以简单地假设在方法完成后发送成功(因为在其他情况下您会得到异常):

public async Task<ActionResult> SendEmail() {
    await _emailSender.SendEmailAsync("test@mail.com", "subject", "something");
    // email was sent, no exception
    return Ok();
}

如果您需要该方法的响应,您可以使用 _emailSender.SendEmailAsync("test@mail.com", "subject", "something") 执行类似 的操作,而无需使用 await 构造(仍然不推荐这种方法):

/// <summary> 
/// Casts a <see cref="Task"/> to a <see cref="Task{TResult}"/>. 
/// This method will throw an <see cref="InvalidCastException"/> if the specified task 
/// returns a value which is not identity-convertible to <typeparamref name="T"/>. 
/// </summary>
public static async Task<T> Cast<T>(this Task task)
{
    if (task == null)
        throw new ArgumentNullException(nameof(task));
    if (!task.GetType().IsGenericType || task.GetType().GetGenericTypeDefinition() != typeof(Task<>))
        throw new ArgumentException("An argument of type 'System.Threading.Tasks.Task`1' was expected");

    await task.ConfigureAwait(false);

    object result = task.GetType().GetProperty(nameof(Task<object>.Result)).GetValue(task);
    return (T)result;
}