I am sending multiple attachments to email addresses in a loop. Attachment is properly getting send to first email address in the list but when it loops ahead for other email addresses in list, the attachment stream in parameter - model becomes 0 in length i. e. 0 bytes.
View Model Code :
public class BulkMailViewModel
{
public string EmailTo { get; set; }
public string EmailSubject { get; set; }
public string EmailBody { get; set; }
public List<HttpPostedFileBase> Attachments { get; set; }
public BulkMailViewModel()
{
Attachments = new List<HttpPostedFileBase>();
}
}
Controller Code : Below Controller method runs the loop for email addressed to send email.
public async Task<ActionResult> SendEmail(BulkMailViewModel model)
{
List<HttpPostedFileBase> attachments = new List<HttpPostedFileBase>();
bool isEmailSentMain = true;
if (model.Attachments != null && model.Attachments.Any())
{
foreach (var attachment in model.Attachments)
{
if (attachment != null)
{
attachments.Add(attachment);
}
}
}
string emailContent = System.Uri.UnescapeDataString(model.EmailBody);
try
{
List<string> clientEmails = new List<string>() { };
clientEmails.Add("abc@abc.com");
clientEmails.Add("pqr@pqr.com");
foreach (var email in clientEmails)
{
try
{
bool isEmailSent = false;
if (email != null && email != "")
{
isEmailSent = await SendBulkEmailAsync(email, model.EmailSubject, emailContent, attachments, true);
if (!isEmailSent)
{
isEmailSentMain = false;
}
}
}
catch (Exception e)
{
isEmailSentMain = false;
return Json(new { status = isEmailSentMain, type = "continue", message = "Error while sending Email." });
}
}
}
catch (Exception e)
{
return Json(new { status = false, message = e.ToString()});
}
}
Mail method Code : This method actually sends the mail.
public async Task<bool> SendBulkEmailAsync(string emailTo, string emailSubject, string emailContent, List<HttpPostedFileBase> attachmentList, bool isBodyHtml = false)
{
List<HttpPostedFileBase> attachments = attachmentList;
using (SmtpClient smtp = new SmtpClient()
{
//My SMTP Settings
})
using (var message = new MailAddress("email@abc.com", emailTo))
{
if (attachments != null)
{
foreach (var attach in attachments)
{
string strFileName = System.IO.Path.GetFileName(attach.FileName);
attach.InputStream.Position = 0;
Attachment attachFile =
new Attachment(attach.InputStream, strFileName, attach.ContentType);
message.Attachments.Add(attachFile);
}
}
message.Subject = emailSubject;
message.Body = emailContent;
message.IsBodyHtml = isBodyHtml;
await smtp.SendMailAsync(message);
return true;
}
}
Can anybody help with this?
You must clone the content of the attach.InputStream
in a local stream to avoid it to be closed by SendMailAsync
:
foreach (var attach in attachments)
{
string strFileName = System.IO.Path.GetFileName(attach.FileName);
attach.InputStream.Position = 0;
MemoryStream tempStream = new MemoryStream();
attach.InputStream.CopyTo(tempStream);
tempStream.Position = 0;
Attachment attachFile =
new Attachment(tempStream, strFileName, attach.ContentType);
message.Attachments.Add(attachFile);
}