locked
SendEmailAsync with Attchment RRS feed

  • Question

  • User1185448985 posted

    I'd like some help applying IEmailSender Interface to a class of mine called EmailSender.

    This interface apply one method called SendEmailAsync(String email, String subject, String message)  which works perfectly!

    In some cases i want to send emails with attachments of type base64 string ,using the same way or something similar is it possible or is there a way i didn't think of to manipulate the class?

    EmailSender.cs

        public class EmailSender: IEmailSender
        {
            public EmailOptions Options { get; set; }
    
            public EmailSender(IOptions<EmailOptions> emailOptions)
            {
                Options = emailOptions.Value;
            }
    
            public Task SendEmailAsync(string email, string subject, string message)
            {
                return Execute(Options.SendGridKey, subject, message, email);
            }
    
            private Task Execute(string sendGridKey, string subject, string message, string email)
            {
                var client = new SendGridClient(sendGridKey);
                var msg = new SendGridMessage()
                {
                    From = new EmailAddress("no-reply@---", "no-reply"),
                    Subject = subject,
                    PlainTextContent = message,
                    HtmlContent = message
                };
                msg.AddTo(new EmailAddress(email));
                try
                {
                    return client.SendEmailAsync(msg);
                }
                catch (Exception ex)
                {
                    Console.WriteLine("{0} First exception caught.", ex);
                }
                return null;
            }
        }
    

    when called

     await _emailSender.SendEmailAsync(
                                       _db.Users.Where("aa@aa.com"
                                        "email subject",
                                        "blah" + blah ");

    Wednesday, February 10, 2021 11:19 PM

Answers

  • User1686398519 posted

    Hi Amani Al, 

    1. I modified the previous answer, you can check it.
    2. What is the purpose of the following method ?
      1. In short, SendEmailAsync(string recipient, string subject, string body) and SendEmailAsync(EmailDto input) can both send emails, but the second method will receive more parameters.
      2. I implemented the Task<bool> SendEmailAsync(string recipient, string subject, string body) method.
    3. is it the old one, but implemented only because of the interface?
      • Because a class that implements a derived interface must implement all members in the derived interface, including all members of the derived interface's base interfaces.
    4. I'm using dependency injection by an instance of IEmailSender not EmailSender
      1. About dependency injection in ASP.NET Core:
        1. ASP.NET Core provides a simple pre-built DI container.
        2. We need to register dependencies in the container. The dependencies can be custom classes or framework classes.
        3. Once the dependencies are registered in the container, you can inject them To wherever needed.
        4. The DI container will automatically inject dependencies where you inject them.
        5. Therefore, as long as you register dependencies in this container, the difference between the two writing methods will not be much.
      2. If you want to use your own writing style, you can click this link.
        • You only need to change the implementation method of SendEmailAsync in the link(SMTP) to your own(SendGrid).

    Regards,

    YihuiSun

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, February 17, 2021 1:51 PM

All replies

  • User1686398519 posted

    Hi Amani Al, 

    According to your needs, I wrote an example, you can refer to it:

    • You can modify the demo below according to your needs.

    UserMailViewModel

        public class UserMailViewModel
        {
            public string Sender { get; set; }
            public string Recipients { get; set; }
            public string Subject { get; set; }
            public string Body { get; set; }
            public IFormFile Attachment { get; set; }
        }

    View

    @ViewBag.Message
    @model DailyCoreMVCDemo.Models.UserMailViewModel
    <form asp-controller="EmailSender" asp-action="Index" method="post"  enctype="multipart/form-data">
        <div class="form-group col-sm-4">
            <label asp-for="Sender"></label>
            <input asp-for="Sender" class="form-control" />
        </div>
        <div class="form-group col-sm-4">
            <label asp-for="Recipients"></label>
            <input asp-for="Recipients" class="form-control" />
        </div>
        <div class="form-group col-sm-4">
            <label asp-for="Subject"></label>
            <input asp-for="Subject" class="form-control" />
        </div>
        <div class="form-group col-sm-4">
            <label asp-for="Body"></label>
            <input asp-for="Body" class="form-control" />
        </div>
        <div class="form-group col-sm-4">
            <label asp-for="Attachment"></label>
            <input asp-for="Attachment" type="file" class="form-control" />
        </div>
        <div class="form-group col-sm-4">
            <button type="submit">Post</button>
        </div>
    </form>

    EmailSender

        public class EmailSender : IEmailSender
        {
            public IFormFile Attachment { get; set; }
            public EmailOptions Options { get; set; }
            public async Task<bool> SendEmailAsync(EmailDto input)
            {
              var client = new SendGridClient("XXXXXX");
                var from = new EmailAddress(Options.SenderAccount, "test");
                var subject = input.Subject;
                var to = new EmailAddress(input.Recipients, "test");
                var htmlContent = input.Body;
                var msg = MailHelper.CreateSingleEmail(from, to, subject, null, htmlContent);
                if (Attachment != null)
                {
                    var ms = new MemoryStream();
                    Attachment.CopyTo(ms);
                    var fileBytes = ms.ToArray();
                    string file = Convert.ToBase64String(fileBytes);
                    msg.AddAttachment(Attachment.FileName, file);
                }
                var response = await client.SendEmailAsync(msg);
                return response.IsSuccessStatusCode;
            }
            public async Task<bool> SendEmailAsync(string recipient, string subject, string body)
            {
              var client = new SendGridClient("XXXXXXXXX");
                var from = new EmailAddress(Options.SenderAccount, "Example User");
                var to = new EmailAddress(recipient, "Example User");
                var htmlContent = body;
                var msg = MailHelper.CreateSingleEmail(from, to, subject, null, htmlContent);
                if (Attachment != null)
                {
                    var ms = new MemoryStream();
                    Attachment.CopyTo(ms);
                    var fileBytes = ms.ToArray();
                    string file = Convert.ToBase64String(fileBytes);
                    msg.AddAttachment(Attachment.FileName, file);
                }
                var response = await client.SendEmailAsync(msg);
                return response.IsSuccessStatusCode;
            } }

    Controller

        public class EmailSenderController : Controller
        {
            private EmailSender _emailSender;
            public EmailSenderController(EmailSender emailSender)
            {
                _emailSender = emailSender;
            }
            public IActionResult Index()
            {
                return View();
            }
            [HttpPost]
            public async Task<IActionResult> Index(UserMailViewModel model)
            {
                //First method
                _emailSender.Attachment = model.Attachment;
                _emailSender.Options = new AspNetCore.Email.EmailOptions { 
                 SenderAccount=model.Sender,
                };
                EmailDto msg = new EmailDto { 
                 Recipients=model.Recipients,
                 Body=model.Body,
                 Subject=model.Body
                };
                var result=await _emailSender.SendEmailAsync(msg);
                //Sencond method
                var result2 = await _emailSender.SendEmailAsync(model.Recipients,model.Subject,model.Body);
                if (result)
                {
                    ViewBag.Message = "success";
                }
                else
                {
                    ViewBag.Message = "fail";
                }
                return View();
            } }

    Startup

    services.AddSingleton<EmailSender>();

    Result

    Best Regards,

    YihuiSun

    Thursday, February 11, 2021 3:02 AM
  • User1185448985 posted

    First, i highly appreciate your help.

    Second, i have some questions to ask you if you could answer them.

    What is the purpose of the following method ? is it the old one, but implemented only because of the interface?

            public Task<bool> SendEmailAsync(string recipient, string subject, string body)
            {
                throw new NotImplementedException();
            }

    And for clarification I'm using dependency injection by an instance of IEmailSender not EmailSender, what is the difference for both ways?

    public class MyController : Controller
        {
           .........
            private readonly IEmailSender _emailSender;
           .........
    
            public StoryController(........., IEmailSender emailSender)
            {
                .........................
                _emailSender = emailSender;
            }
    }

    Best regards

    Friday, February 12, 2021 6:07 PM
  • User1686398519 posted

    Hi Amani Al, 

    1. I modified the previous answer, you can check it.
    2. What is the purpose of the following method ?
      1. In short, SendEmailAsync(string recipient, string subject, string body) and SendEmailAsync(EmailDto input) can both send emails, but the second method will receive more parameters.
      2. I implemented the Task<bool> SendEmailAsync(string recipient, string subject, string body) method.
    3. is it the old one, but implemented only because of the interface?
      • Because a class that implements a derived interface must implement all members in the derived interface, including all members of the derived interface's base interfaces.
    4. I'm using dependency injection by an instance of IEmailSender not EmailSender
      1. About dependency injection in ASP.NET Core:
        1. ASP.NET Core provides a simple pre-built DI container.
        2. We need to register dependencies in the container. The dependencies can be custom classes or framework classes.
        3. Once the dependencies are registered in the container, you can inject them To wherever needed.
        4. The DI container will automatically inject dependencies where you inject them.
        5. Therefore, as long as you register dependencies in this container, the difference between the two writing methods will not be much.
      2. If you want to use your own writing style, you can click this link.
        • You only need to change the implementation method of SendEmailAsync in the link(SMTP) to your own(SendGrid).

    Regards,

    YihuiSun

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, February 17, 2021 1:51 PM