UPDATE I tested this with Excel documents instead of PDFs, and it worked. Why won't it work with PDFs??
I am trying to add X amount of attachments to an e-mail by iterating over a list of file path strings. Instead I get X attachments, but they're all copies of the same file. So the amount of attachments is correct, but their content is not.
This happens even though:
I am using FluentEmail to send e-mails. Also, I am building upon the following example (see 'Multiple attachments' section).
I added Debug.WriteLine(path) just to check if I am able to correctly output the strings in the loop, which I were.
My method:
public async void SendInvoicesEmail() {
try {
using (SqlConnection con = new(ConnectionString.connectionString))
using (SqlCommand cmd = new("query text", con)) {
con.Open();
SmtpSender sender = new SmtpSender(() => new SmtpClient(host: "smtp.office365.com") {
EnableSsl = true,
UseDefaultCredentials = false,
DeliveryMethod = SmtpDeliveryMethod.Network,
Credentials = new NetworkCredential("email", "password"),
Port = 587
});
Email.DefaultSender = sender;
IFluentEmail newEmail = Email
.From("email")
.To("email")
.Subject("subject text")
.Body("body text");
var attachList = new List<FluentEmail.Core.Models.Attachment>();
// SourcePathList contains all the file paths I need to reference.
foreach (string path in SourcePathList) {
string fileName = Path.GetFileName(path);
var attachment = new FluentEmail.Core.Models.Attachment {
Data = File.OpenRead(path),
ContentType = "application/pdf",
Filename = $"{fileName}"
};
attachList.Add(attachment);
Debug.WriteLine(path);
}
newEmail.Attach(attachList);
SourcePathList.Clear();
FluentEmail.Core.Models.SendResponse result = await newEmail.SendAsync();
if (result.Successful) {
cmd.ExecuteNonQuery();
}
}
} catch (Exception ex) {
MessageBox.Show(ex.Message, "Message", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
I have tried:
newEmail.AttachFromFilename.newEmail.Send instead of .SendAsync.ContentType for older PDFs (even though I have updated software): "application/x-pdf".But none of the above made any difference.
The three items present are distinct, yet only the last item is added as file in the 3 attachments. Does ContentId matter?
I think stream object is not getting refresh in loop and it is adding same file content for each attachment.
you should use your stream object in using statement as below
I am also using similar functionality on my web using System.Net.Mail
Earlier I have suggested an untested code, which had a bug. Now I have tested your code again and it's working as expected. here is complete method which I have run in a MVC controller.
public async void SendInvoicesEmail()
{
try
{
SmtpSender sender = new SmtpSender(() => new SmtpClient(host: "smtp.sendgrid.net")
{
EnableSsl = true,
UseDefaultCredentials = false,
DeliveryMethod = SmtpDeliveryMethod.Network,
Credentials = new NetworkCredential("user", "password"),
Port = 587
});
Email.DefaultSender = sender;
IFluentEmail newEmail = Email
.From("Admin@admin.com")
.To("user@user.com")
.Subject("I am feeling lucky")
.Body("This email is for stack overflow problem solution.");
var attachList = new List<FluentEmail.Core.Models.Attachment>();
// SourcePathList contains all the file path on my machine.
var SourcePathList = new List<string>
{
"C:\\Consolidate_09122021085902.xlsx",
"C:\\PaySlip_15022022075604.xlsx",
"C:\\RateCard_14022022104134.xlsx"
};
foreach (string path in SourcePathList)
{
string fileName = Path.GetFileName(path);
var attachment = new FluentEmail.Core.Models.Attachment
{
Data = System.IO.File.OpenRead(path),
ContentType = "application/pdf",
Filename = $"{fileName}"
};
attachList.Add(attachment);
Debug.WriteLine(path);
}
newEmail.Attach(attachList);
SourcePathList.Clear();
FluentEmail.Core.Models.SendResponse result = await newEmail.SendAsync();
}
catch (Exception ex)
{
// write log file
}
}
Here is Email Output