c# send mail to multiple recipients - c#

I use this to send mails, I've defined some package variables which contains values:
public MailProperties(ScriptObjectModel dts)
{
if (
!string.IsNullOrEmpty((string)dts.Variables["$Package::mailFrom"].Value) &&
!string.IsNullOrEmpty((string)dts.Variables["$Package::mailTo"].Value) &&
!string.IsNullOrEmpty((string)dts.Variables["$Package::mailPwd"].GetSensitiveValue()) &&
!string.IsNullOrEmpty((string)dts.Variables["$Package::mailSmtp"].Value) &&
!string.IsNullOrEmpty((string)dts.Variables["$Package::mailPort"].Value)
)
{
fromMail = (string)dts.Variables["$Package::mailFrom"].Value;
toMail = (string)dts.Variables["$Package::mailTo"].Value;
bccMail = (string)dts.Variables["$Package::mailBcc"].Value;
accountPassword = (string)dts.Variables["$Package::mailPwd"].GetSensitiveValue();
accountSmtp = (string)dts.Variables["$Package::mailSmtp"].Value;
accountSmtpPort = (string)dts.Variables["$Package::mailPort"].Value;
useSSL = (bool)dts.Variables["$Package::useSSL"].Value;
pathAttachment = new List<string>();
pathAttachment.Add((string)dts.Variables["User::pathFileReject"].Value);
pathAttachment.Add((string)dts.Variables["User::pathFileReject2"].Value);
}
else
{
throw new Exception("error text...");
}
}
I need to send mail to more people, so I set mailTo with mail1#gmail.com, mailBcc as mail2#gmail.com and it works, but if I set mailBcc as "mail2#gmail.com, mail3#gmail.com" or "mail2#gmail.com; mail3#gmail.com" it doesn't work, how I can do that?
EDIT: this is the sendMail function
public static void sendMail(MailProperties mailProperties, ReportETL reportETL)
{
MimeMessage message = new MimeMessage();
message.From.Add(new MailboxAddress("text..", mailProperties.fromMail));
message.To.Add(new MailboxAddress(mailProperties.toMail));
message.Subject = "text...";
if (!string.IsNullOrEmpty(mailProperties.bccMail))
{
message.Bcc.Add(new MailboxAddress(mailProperties.bccMail));
}
BodyBuilder bodyBuilder = new BodyBuilder();
bodyBuilder.HtmlBody = ReportETLService.getHtmlFromReporETL(reportETL);
mailProperties.pathAttachment.Where(x => File.Exists(x)).ToList().ForEach(y => bodyBuilder.Attachments.Add(y));
message.Body = bodyBuilder.ToMessageBody();
try
{
SmtpClient smtpClient = new SmtpClient();
smtpClient.Connect(mailProperties.accountSmtp, int.Parse(mailProperties.accountSmtpPort), mailProperties.useSSL);
smtpClient.Authenticate(mailProperties.fromMail, mailProperties.accountPassword);
smtpClient.Send(message);
smtpClient.Disconnect(true);
}
catch (Exception e) { throw new Exception("text... " + e.Message); }
}

according to documentation message.To is list type.So you can add more adress like this.
InternetAddressList list = new InternetAddressList();
list.add(adress1)
list.add(adress2)
list.add(adress3)
list.add(adress4)
message.To.AddRange(list);

Instead of using BCC (which would be an option, but has the problem of max count) just iterate over all mail addresses and send one for each recipient. (Not to fast or you get other problems)
This way it should be "easier" to spot mails that will not get delivered.

Well, assuming that your toMail, ccMail, and bccMail properties are just strings and not lists of strings, you could do something like this:
InternetAddressList list;
if (!string.IsNullOrEmpty(mailProperties.toMail) && InternetAddressList.TryParse (mailProperties.toMail, out list))
message.To.AddRange(list);
if (!string.IsNullOrEmpty(mailProperties.ccMail) && InternetAddressList.TryParse (mailProperties.ccMail, out list))
message.Cc.AddRange(list);
if (!string.IsNullOrEmpty(mailProperties.bccMail) && InternetAddressList.TryParse (mailProperties.bccMail, out list))
message.Bcc.AddRange(list);

Related

How do I make Email button sent email for selected listbox item?

We have an app that sends email to person(requestor) selected from a combobox. It only sends one email.
New requirement is that we want to send more than one email to more than one person.
The project owner does not want to replace the current combobox with a listbox. This will require additional database work.
So what was suggested to me for a solution is to add a listbox which is populated with the same information (name objects from the database) as the combobox.
The listbox will be used only when the user want to send email to extra people.
How do I modify the code for this button so that it sends email to the requestor selected in the combobox (which it is currently doing) and also send email to any requestor selected from the listbox?
Before the email is sent, I want to check to make sure that the selected requestor from the combobox is not also selected in the listbox. I do not want the requester to receive two email.
Here is the Listbox which has the same data for the requestor as the combobox.
public async void PopulateAdditionalStaffEmailListBox()
{
List<GetRequestorInfoModel> requestors = new List<GetRequestorInfoModel>();
try
{
requestors = await FTACaseReset.Controllers.RequestorInfoController.GetAllRequestorInfoes();
requestors = requestors.OrderBy(x => x.DisplayName).ToList(); //Has 15 items
//Populate AdditionalStaffEmailListBox
for (int i = 0; i < requestors.Count; i++)
{
ListBoxItem requestor = new ListBoxItem();
requestor.Text = requestors[i].DisplayName;
requestor.Value = requestors[i].RequestorInfoID;
AdditionalStaffEmailListBox.Items.Add(requestor.Text).ToString();
}
}
catch (Exception ex)
{
string errorMsg = string.Format("An error has occured in {0}. \nException:\n{1}", "AdditionalStaffEmailListBox()", ex.Message);
MessageBox.Show(errorMsg, "Application Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Here is the code for the button that is currently sending email to requester selected from the combobox
private async void SendEmail(int selectedBatch)
{
string message = "The following records have been prepped for processing. Valid cases will be processed.{0}{1}{2}";
string requestorName = string.Empty;
string requestorEmail = string.Empty;
List<GetCandidateCaseModel> masterCandidateCasesListToDisplay = new List<GetCandidateCaseModel>();
try
{
masterCandidateCasesListToDisplay = await Controllers.CandidateCaseController.GetAllCandidates();
masterCandidateCasesListToDisplay = masterCandidateCasesListToDisplay.Where(x => x.BatchNumber == selectedBatch && x.RejectionReason != null).ToList();
if (masterCandidateCasesListToDisplay.Count > 0)
{
requestorName = masterCandidateCasesListToDisplay[0].RequestorInfo.DisplayName;
requestorEmail = masterCandidateCasesListToDisplay[0].RequestorInfo.Email;
using (MailMessage mailMessage = new MailMessage())
{
mailMessage.From = new MailAddress("NoReply_FTA#courts.state.mn.us");
//Uncomment after testing June 2019
MailAddress to = new MailAddress(requestorEmail);
mailMessage.To.Add(to);
string ccEmailAddress = Authentication.GetADEmail();
if (ccEmailAddress.Length > 0)
{
MailAddress ccto = new MailAddress(ccEmailAddress);
mailMessage.CC.Add(ccto);
}
mailMessage.Subject = "FTA Case Reset Notice";
mailMessage.Body = message;
mailMessage.IsBodyHtml = true;
SmtpClient smtpClient = new SmtpClient();
smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
smtpClient.Send(mailMessage);
MessageBox.Show("An email has been sent to " + requestorName, "Email", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
else
MessageBox.Show("No Requestor was found. Unable to send an email.", "Email", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
catch (Exception ex)
{
string errorMsg = string.Format("An error has occured in {0}. \nException:\n{1}", "SubmitButton_Click()", ex.Message);
MessageBox.Show(errorMsg, "Application Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Its quite difficult understand your code if you dont show your custom classes.
The following code should work but be aware that comparing display names is not the best idea so if you can compare them by some id, do that instead.
private async void SendEmail(int selectedBatch)
{
string message = "The following records have been prepped for processing. Valid cases will be processed.{0}{1}{2}";
string requestorName = string.Empty;
string requestorEmail = string.Empty;
List<GetCandidateCaseModel> masterCandidateCasesListToDisplay = new List<GetCandidateCaseModel>();
try
{
masterCandidateCasesListToDisplay = await Controllers.CandidateCaseController.GetAllCandidates();
var selectedCandidate = masterCandidateCasesListToDisplay.Where(x => x.BatchNumber == selectedBatch && x.RejectionReason != null).ToList();
if (masterCandidateCasesListToDisplay.Count > 0)
{
SmtpClient smtpClient = new SmtpClient();
smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
string requestorName0 = selectedCandidate[0].RequestorInfo.DisplayName;
string requestorEmail0 = selectedCandidate[0].RequestorInfo.Email;
MailMessage mailMessage = new MailMessage();
MailAddress to = new MailAddress(requestorEmail);
mailMessage.From = new MailAddress("NoReply_FTA#courts.state.mn.us");
mailMessage.To.Add(to);
mailMessage.Subject = "FTA Case Reset Notice";
mailMessage.Body = message;
mailMessage.IsBodyHtml = true;
string ccEmailAddress = Authentication.GetADEmail();
if (ccEmailAddress.Length > 0)
{
MailAddress ccto = new MailAddress(ccEmailAddress);
mailMessage.CC.Add(ccto);
}
foreach (ListViewItme item in AdditionalStaffEmailListBox.SelectedItems)
{
candidate = masterCandidateCasesListToDisplay.First(x => x.RequestorInfo.DisplayName == item.Value);
requestorName = candidate.RequestorInfo.DisplayName;
requestorEmail = candidate.RequestorInfo.Email;
if (requestorEmail0 == requestorEmail)
{
continue;
}
to = new MailAddress(requestorEmail);
mailMessage.To.Add(to);
ccEmailAddress = Authentication.GetADEmail();
if (ccEmailAddress.Length > 0)
{
MailAddress ccto = new MailAddress(ccEmailAddress);
mailMessage.CC.Add(ccto);
}
MessageBox.Show("An email has been sent to " + requestorName, "Email", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
smtpClient.Send(mailMessage);
}
else
{
MessageBox.Show("No Requestor was found. Unable to send an email.", "Email", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
catch (Exception ex)
{
string errorMsg = string.Format("An error has occured in {0}. \nException:\n{1}", "SubmitButton_Click()", ex.Message);
MessageBox.Show(errorMsg, "Application Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}

Image not displayed in Outlook in ASP

After sending an email the logo is not displayed in Outlook but it works in Gmail.
I found that in the inspect element that the image src is changed into blockedimagesrc
In my Controller :
var NotifyCompany = new NotifyCompany()
{
Email = model.regE,
EmailTo = contact.GetPropertyValue<string>("email"),
DateRegistered = DateTime.UtcNow
};
EmailHelpers.SendEmail(NotifyCompany, "NotifyCompany", "New Client Registered");
Helpers :
public static ActionResponse SendEmail(IEmail model, string emailTemplate, string subject, List<HttpPostedFileBase> files = null)
{
try
{
var template =
System.IO.File.ReadAllText(HttpContext.Current.Server.MapPath(string.Format("~/Templates/{0}.cshtml", emailTemplate)));
var body = Razor.Parse(template, model);
var attachments = new List<Attachment>();
if (files != null && files.Any())
{
foreach (var file in files)
{
var att = new Attachment(file.InputStream, file.FileName);
attachments.Add(att);
}
}
var email = Email
.From(ConfigurationManager.AppSettings["Email:From"], "myWebsiteEmail")
.To(model.EmailTo)
.Subject(subject)
.Attach(attachments)
.Body(body).BodyAsHtml();
email.Send();
return new ActionResponse()
{
Success = true
};
}
catch (Exception ex)
{
return new ActionResponse()
{
Success = false,
ErrorMessage = ex.Message
};
}
}
In my Email Template :
<img src="/mysite.com/image/logo.png"/>
Any help would be appreciated.
Outlook web access will block any images by default - only if the user chooses to display/download images these will be displayed/downloaded. I am not sure if it is possible to adjust the default behavior by using office 365 admincenter or the OWA settings.
Some time ago it was possible to work around this by using it as a background image inside a table>tr>td cell background-image css property.
EDIT
Checked a recent project of myself, where we are sending notification mails about tickets. The site logo is displayed correctly in outlook/owa - without adding the recipient to the trusted list:
using (MailMessage mm = new MailMessage(sender, header.RecipientAddress, header.Subject, header.Body))
{
mm.Body = header.Body;
mm.BodyEncoding = Encoding.UTF8;
mm.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;
mm.Priority = priority == IntMailPriority.High ? MailPriority.High : MailPriority.Normal;
mm.IsBodyHtml = bodyIsHtml;
// logo
if (bodyIsHtml)
{
AlternateView htmlView = AlternateView.CreateAlternateViewFromString(header.Body, Encoding.UTF8, "text/html");
string logoPath = $"{AppDomain.CurrentDomain.BaseDirectory}\\images\\logo_XXX.png";
LinkedResource siteLogo = new LinkedResource(logoPath)
{
ContentId = "logoId"
};
htmlView.LinkedResources.Add(siteLogo);
mm.AlternateViews.Add(htmlView);
}
// create smtpclient
SmtpClient smtpClient = new SmtpClient(smtpSettings.ServerAddress, smtpSettings.Port)
{
Timeout = 30000,
DeliveryMethod = SmtpDeliveryMethod.Network
};
// set relevant smtpclient settings
if (smtpSettings.UseTlsSsl)
{
smtpClient.EnableSsl = true;
// needed for invalid certificates
ServicePointManager.ServerCertificateValidationCallback = delegate { return true; };
}
if (smtpSettings.UseAuth)
{
smtpClient.UseDefaultCredentials = false;
NetworkCredential smtpAuth = new NetworkCredential { UserName = smtpSettings.Username, Password = smtpSettings.Password };
smtpClient.Credentials = smtpAuth;
}
smtpClient.Timeout = smtpSettings.SendingTimeout * 1000;
// finally sent mail \o/ :)
try
{
smtpClient.Send(mm);
}
catch (SmtpException exc)
{
throw new ProgramException(exc, exc.Message);
}
catch (InvalidOperationException exc)
{
throw new ProgramException(exc, exc.Message);
}
catch (AuthenticationException exc)
{
throw new ProgramException(exc, exc.Message);
}
}
Afterwards the logo is referred to as
<IMG alt="Intex Logo" src="cid:logoId">
inside the generated html.

C# MVC Send email to multiple recipient

I have trying to send one mail to Test1 and Test2. I tried separating the recipients with ; like To ="Test1#stanleytests.co.za;Test2#stanleytests.co.za" that did not work and also tried concatenating them by doing To="Test1#stanleytests.co.za"+"Test2#stanleytests.co.za" that did not work. now I wrote and Array. the thing with my array is that it sends 2 mails, so i only want to sent one mail to two recipient.
private void SendDailyEmails(DateTime today)
{
today = DateTime.Now;
string recipient = "Test1#stanleytests.co.za,Test2#stanleytests.co.za";
string[] emailTo = recipient.Split(',');
for (int i = 0; i < emailTo.GetLength(0); i++)
{
var emailObject = new EmailObject
{
To = emailTo[i],
Cc = "me#stanleytests.co.za",
Subject = "Daily Mail",
Body = "Good morning, <br/><br/> This email is sent to you: <strong> "please be adviced" </strong> <br/><br/>Regards"
};
_emailService.SendEmail(emailObject);
}
}
Please assist here.thanks
Partially your code, see the example below. Honestly, I don't have access to our SMTP servers here, so, I can't really test it. This should set you on the right path. I am guessing your issue really is that you are missing: new MailAddress(i) .
Hope this helps, there are more reference material on MSDN's site.
private void SendDailyEmails()
{
var today = DateTime.Now;
var recipient = "Test1#stanleytests.co.za,Test2 #stanleytests.co.za";
var message = new MailMessage()
{
From = new MailAddress("Somebody"),
CC = { new MailAddress("me#stanleytests.co.za") },
Subject = "Daily Mail",
Body = #"Good morning, <br/><br/> This email is sent to you: <strong> ""please be adviced"" </strong> <br/><br/>Regards",
IsBodyHtml = true
};
foreach (var i in recipient.Split(',').ToList())
{
message.To.Add(new MailAddress(i));
}
// do your "_emailService.SendEmail(message);
}
We don't know what library you are using for sending emails thus I can only make suggestions.
The convention for joining several email address is to separate them with ; :
emailObject.To = String.Join(";", recipient.Split(','));
string body = "Body of email";
var message = new MailMessage();
message.To.Add(new MailAddress("example#exaple.com"));
message.To.Add(new MailAddress("example2#exaple.com"));
message.From = new MailAddress("example#gmail.com", "Name");
message.Subject = "This is the subject";
message.Body = body;
message.IsBodyHtml = true;

Create a list of disposable emails

I'm sending emails with asp.net core 2.0 like this
public string EmailServiceSend(string body, string subject = null, string to = null,
string multipleRecipients = null, string attachmentUrl = null, string smtpClient = null,
string userCredential = null, string userPassword = null, string from = null, bool template = false,
string templateRoute = null)
{
try
{
SmtpClient client = new SmtpClient("mysmtpserver");
client.UseDefaultCredentials = false;
client.Credentials = new NetworkCredential("username", "password");
MailMessage mailMessage = new MailMessage();
mailMessage.From = new MailAddress("whoever#me.com");
mailMessage.To.Add("receiver#me.com");
mailMessage.Body = body;
mailMessage.Subject = subject;
client.Send(mailMessage);
}
catch(Exception ex)
{
ex.Message.ToString();
}
return "Email sended"
}
I want to know, how can I create a list of email domains to block and send an error message. For example I want to block this domains:
0-mail.com
0815.ru
0clickemail.com
0wnd.net
and then send a response into my return statement for example:
if(listofblockmails == true){
return "You can't add this email domain, change it please"
}
How can I achieve that? Regards
Try using Linq:
Lets say you have this List:
List<string> listofblockmails = new List<string>();
listofblockmails.Add("0-mail.com");
listofblockmails.Add("0815.ru");
listofblockmails.Add("0clickemail.com");
listofblockmails.Add("0wnd.net");
You can do as below:
if (listofblockmails.Contains("emailToBeChecked.com"))
{
//return "You can't add this email domain, change it please";
}
else
{
//send
//return "Email sended";
}
And let Garbage collector do the disposal.
You can simply parse the email address and get the domain part, and compare againist a list of bad domains. If the domain is present in your bad domain list, return messge.
You can create a method like this.
private bool IsGoodDomain(string email)
{
if (string.IsNullOrEmpty(email))
return false;
var badDomains = new List<string>
{
"0815.ru",
"0wnd.net"
};
var r = email.Split('#');
if (!r.Any()) return false;
var domainName = r.Last();
return !badDomains.Contains(domainName, StringComparer.InvariantCultureIgnoreCase);
}
and call this method in your other method
if(IsGoodDomain(someEmailAddressVariable))
{
//contnue sending
}
else
{
// return the error message
}

C# Send Email or SMS Async using Azure and Fire&Forget

I'm looking for a simple way to fire&forget either a Twilio SMS or an Email and I thought that Azure Queue or Bus does exactly that. But then I start reading about each one and it seems they were designed to do something more complicated.
Question:
What's the best way to implement a "Fire&Forget" method/call so that I know I sent an email but my application does NOT need to stop waiting for the message to actually leave.
Here is one sync version for sending mail with SendGrid. You can very easily transform it to async.
public void SendMail(MailAddress #from, MailAddress[] to, string subject, AlternateView[] alternateMessageBodyViews, Attachment[] attachments)
{
_validationService.StringIsNullOrEmpty(subject, "subject");
_validationService.Null(from, "from");
_validationService.StringIsNullOrEmpty(from.Address, "from.Address");
_validationService.Null(to, "to");
/* Important Notice
* SendGrid has 20480000 bytes limitation for the total message size. Approx. 19.5 MB
* BUT attachments are Base64 encoded therefore 15MB of attachments will actually become 20 MB when encoded.
* Therefore we need to cut down the attachments total ( cumulative ) size to 12 MB which will make 16 MB after base64
* Combined with other message information like message headers, attachments headers, etc. will keep us away from the 19.5MB limit
*/
long approximateTotalMessageMaxSizeInBytes = 0;
MailMessage mailMsg = new MailMessage();
// From
mailMsg.From = new MailAddress(from.Address, from.DisplayName);
approximateTotalMessageMaxSizeInBytes += Convert.ToBase64String(Encoding.UTF8.GetBytes(from.Address)).Length;
approximateTotalMessageMaxSizeInBytes += Convert.ToBase64String(Encoding.UTF8.GetBytes(from.DisplayName)).Length;
// To
foreach (MailAddress toMailAddress in to)
{
mailMsg.To.Add(new MailAddress(toMailAddress.Address, toMailAddress.DisplayName));
approximateTotalMessageMaxSizeInBytes += Convert.ToBase64String(Encoding.UTF8.GetBytes(toMailAddress.Address)).Length;
approximateTotalMessageMaxSizeInBytes += Convert.ToBase64String(Encoding.UTF8.GetBytes(toMailAddress.DisplayName)).Length;
}
// Subject and multipart/alternative Body
mailMsg.Subject = subject;
approximateTotalMessageMaxSizeInBytes += Convert.ToBase64String(Encoding.UTF8.GetBytes(subject)).Length;
if (alternateMessageBodyViews != null)
{
foreach (AlternateView alternateView in alternateMessageBodyViews)
{
mailMsg.AlternateViews.Add(alternateView);
approximateTotalMessageMaxSizeInBytes += (long)(alternateView.ContentStream.Length * 1.33);
}
}
if (attachments != null)
{
foreach (Attachment attachment in attachments)
{
mailMsg.Attachments.Add(attachment);
approximateTotalMessageMaxSizeInBytes += (long)(attachment.ContentStream.Length * 1.33);
}
}
if (approximateTotalMessageMaxSizeInBytes > long.Parse(ConfigurationManager.AppSettings["TotalMessageMaxSizeInBytes"]))
{
throw new MailMessageTooBigException(
string.Format("Message total bytes limit is {0}. This message is approximately {1} bytes long.",
approximateTotalMessageMaxSizeInBytes));
}
try
{
_mailSender.Send(mailMsg);
}
catch(Exception exception) // swallow the exception so the server do not blow up because of a third party service.
{
_logger.Exception("SendGridMailService", _currentUserProvider.CurrentUserId, exception);
}
string logFrom = string.Format("{0} <{1}>", from.DisplayName, from.Address);
string[] logTo = to.Select(t => string.Format("{0} <{1}>", t.DisplayName, t.Address)).ToArray();
string[] atts = (attachments == null) ? null : attachments.Select(att => att.Name).ToArray();
_logger.SendEmail(
_currentUserProvider.CurrentSystemUser.UserName,
logFrom,
logTo,
subject,
atts);
}
And one simple async EAP style version from here :
public void SendAsyncMail()
{
MailMessage mail = new MailMessage();
mail.From = new MailAddress("Enter from mail address");
mail.To.Add(new MailAddress("Enter to address #1"));
mail.To.Add(new MailAddress("Enter to address #2"));
mail.Subject = "Enter mail subject";
mail.Body = "Enter mail body";
SmtpClient smtpClient = new SmtpClient();
Object state = mail;
//event handler for asynchronous call
smtpClient.SendCompleted += new SendCompletedEventHandler(smtpClient_SendCompleted);
try
{
smtpClient.SendAsync(mail, state);
}
catch (Exception ex)
{
}
}
void smtpClient_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
MailMessage mail = e.UserState as MailMessage;
if (!e.Cancelled && e.Error != null)
{
//message.Text = "Mail sent successfully";
}
}
And third one TAP style from here :
var message = new MailMessage("from", "to", "subject", "body"))
var client = new SmtpClient("host");
client.SendCompleted += (s, e) => {
client.Dispose();
message.Dispose();
};
client.SendAsync(message, null);
For Twilio SMS API you can start with the tutorial right here. Full async support.

Categories