【问题标题】:ASP.NET Identity UserManager IIdentityMessageService pass extra parameters to SendAsyncASP.NET Identity UserManager IIdentityMessageService 将额外参数传递给 SendAsync
【发布时间】:2016-12-19 12:04:23
【问题描述】:

我已经通过扩展 IIdentityMessageService 成功地为 UserManager 创建了自定义电子邮件服务提供商:

public class ExchangeEmailService : IIdentityMessageService
{
    public async Task SendAsync(IdentityMessage message)
    {
        using (var client = new SmtpClient())
        {
            client.Host = "mail.example.com";
            client.DeliveryMethod = SmtpDeliveryMethod.Network;
            client.UseDefaultCredentials = false;
            client.Credentials = new NetworkCredential(@"noreply", "P@ssw0rd");

            var from = new MailAddress("no-reply@example.com");
            var to = new MailAddress(message.Destination);

            var mailMessage = new MailMessage(from, to)
            {
                Subject = message.Subject,
                Body = message.Body,
                IsBodyHtml = true
            };
            await client.SendMailAsync(mailMessage);
        }
    }
}

UserManager 的 Create 中,我正在创建我的服务的新实例并将其分配给 EmailService

userManager.EmailService = new ExchangeEmailService();

这一切都很好,但我需要从不同的电子邮件地址发送电子邮件,这取决于调用它的位置,不幸的是,UserManager.SendEmailAsync 不允许我传递除 userId、主题和正文之外的任何内容。

理想情况下,我希望能够在调用SendEmailAcync 或枚举值时指定电子邮件地址。

我在 UserManager source 中进行了搜索,并考虑过创建自定义 SendEmailAsync 实现,但我必须更改多个位置 - IIdentityMessageService、UserManager。

我知道我可以创建新界面并在其上构建我的电子邮件发送类,但我希望尽量减少更改。

我想得到什么:
我想要包含邮箱名称的枚举:

public enum Mailboxes
{
    Noreply = 0,
    Service = 1,
    Contact = 2
}

并且能够使用该附加参数调用SendEmailAsync

await UserManager.SendEmailAsync(user.Id, "Account created", "Nice email content.", Mailboxes.Noreply );

我知道我可以设置不同的标题并使用相同的电子邮件地址,但这是我的要求。

我该怎么做?

【问题讨论】:

  • 如果不重载 SendEmailAsync 在您的 ApplicationUserManager 类中扩展 Identity 中的 UserManager,我看不到解决方法。然后,您可以扩展 IdentityMessage 类,使其具有 FromAddress 属性。您的新重载SendEmailAsync 将具有fromAddress 参数,您可以使用该参数创建自定义IdentityMessage 的实例。但是,您还必须在新的SendEmailAsync 中查找当前用户才能检索目标地址。
  • @philreed 我考虑过扩展IdentityMessage,将我的类的实例传递给SendEmailAsync,然后在SendAsync内部检查IdentityMessage是否是MyEmailMessage,然后向上转换并使用新的财产。我会再等一会儿,因为我想避免重新发明轮子。
  • 是的,我不明白为什么这不起作用,它比我在之前的评论中建议的要简单。
  • @Misiu,一个技巧是创建一个模型来存储您想要发送到服务的内容,然后将其序列化(可能是 JSON)作为方法调用的主体。然后,该服务将反序列化模型,使用自定义信息构建电子邮件,然后发送电子邮件。

标签: c# asp.net asp.net-web-api asp.net-identity-2


【解决方案1】:

一个技巧是创建一个模型来存储您想要发送到服务的内容

public class MessageBody {
    public string Body { get; set; }
    public MailBoxes Source { get; set; }
}

然后将其序列化(可能是 JSON)作为 SendEmailAsync 方法调用的 body 参数。

var message = new MessageBody {
    Body = "Nice email content.",
    Source = Mailboxes.Noreply
};

var body = JsonConvert.SerializeObject(message);

await UserManager.SendEmailAsync(user.Id, "Account created", body);

然后该服务将反序列化模型,使用自定义信息构建电子邮件,然后发送电子邮件。

public class ExchangeEmailService : IIdentityMessageService {
    readonly IMailBoxProvider provider;

    public ExchangeEmailService(IMailBoxProvider provider) {
        this.provider = provider;
    }

    public async Task SendAsync(IdentityMessage message) {
        using (var client = new SmtpClient()) {
            client.Host = "mail.example.com";
            client.DeliveryMethod = SmtpDeliveryMethod.Network;
            client.UseDefaultCredentials = false;
            client.Credentials = new NetworkCredential(@"noreply", "P@ssw0rd");

            //Get the body and from address
            var fromEmailAddress = "default-email@example.com";
            var body = message.Body;
            try {
                var msg = JsonConvert.DeserializeObject<MessageBody>(body);
                if(msg != null) {
                    body = msg.Body;
                    fromEmailAddress = provider.GetMailbox(msg.Source);
                }
            } catch { }

            var from = new MailAddress(fromEmailAddress);
            var to = new MailAddress(message.Destination);

            var mailMessage = new MailMessage(from, to)
            {
                Subject = message.Subject,
                Body = body,
                IsBodyHtml = true
            };
            await client.SendMailAsync(mailMessage);
        }
    }
}

只需确保将其分配给UserManager.EmailService

userManager.EmailService = new ExchangeEmailService(new MailBoxProvider());

【讨论】:

    猜你喜欢
    • 2018-10-07
    • 1970-01-01
    • 2011-03-06
    • 2021-02-27
    • 2012-01-04
    • 1970-01-01
    • 2016-06-08
    • 1970-01-01
    相关资源
    最近更新 更多