How can I silently send Outlook email? - c#

I've got this code that sends an email with attachment[s]:
internal static bool EmailGeneratedReport(List<string> recipients)
{
bool success = true;
try
{
Microsoft.Office.Interop.Outlook.Application app = new Microsoft.Office.Interop.Outlook.Application();
MailItem mailItem = app.CreateItem(OlItemType.olMailItem);
Recipients _recipients = mailItem.Recipients;
foreach (string recip in recipients)
{
Recipient outlookRecipient = _recipients.Add(recip);
outlookRecipient.Type = (int)OlMailRecipientType.olTo;
outlookRecipient.Resolve();
}
mailItem.Subject = String.Format("Platypus Reports generated {0}", GetYYYYMMDDHHMM());
List<String> htmlBody = new List<string>
{
"<html><body><img src=\"http://www.platypus.com/wp-content/themes/duckbill/images/pa_logo_notag.png\" alt=\"Pro*Act logo\" ><p>Your Platypus reports are attached.</p>"
};
htmlBody.Add("</body></html>");
mailItem.HTMLBody = string.Join(Environment.NewLine, htmlBody.ToArray());
. . . // un-Outlook-specific code elided for brevity
FileInfo[] rptsToEmail = GetLastReportsGenerated(uniqueFolder);
foreach (var file in rptsToEmail)
{
String fullFilename = Path.Combine(uniqueFolder, file.Name);
if (!File.Exists(fullFilename)) continue;
if (!file.Name.Contains(PROCESSED_FILE_APPENDAGE))
{
mailItem.Attachments.Add(fullFilename);
}
MarkFileAsSent(fullFilename);
}
mailItem.Importance = OlImportance.olImportanceHigh;
mailItem.Display(false);
}
catch (System.Exception ex)
{
String exDetail = String.Format(ExceptionFormatString, ex.Message,
Environment.NewLine, ex.Source, ex.StackTrace, ex.InnerException);
MessageBox.Show(exDetail);
success = false;
}
return success;
}
However, it pops up the email window when ready, which the user must respond to by either sending or canceling. As this is in an app that sends email based on a timer generating reports to be sent, I can't rely on a human being present to hit the "Send" button.
Can Outlook email be sent "silently"? If so, how?
I can send email silently with gmail:
private void EmailMessage(string msg)
{
string FROM_EMAIL = "sharedhearts#gmail.com";
string TO_EMAIL = "cshannon#platypus.com";
string FROM_EMAIL_NAME = "B. Clay Shannon";
string TO_EMAIL_NAME = "Clay Shannon";
string GMAIL_PASSWORD = "theRainNSpainFallsMainlyOnDonQuixotesHelmet";
var fromAddress = new MailAddress(FROM_EMAIL, FROM_EMAIL_NAME);
var toAddress = new MailAddress(TO_EMAIL, TO_EMAIL_NAME);
string fromPassword = GMAIL_PASSWORD;
string subject = string.Format("Log msg from ReportScheduler app sent
{0}", DateTime.Now.ToLongDateString());
string body = msg;
var smtp = new SmtpClient
{
Host = "smtp.gmail.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
};
using (var message = new MailMessage(fromAddress, toAddress)
{
Subject = subject,
Body = body
})
{
smtp.Send(message);
}
}
...but when I do that, I have to supply my gmail password, and I don't really want to do that (expose my password in the source code).
So, how can I gain the benefits of gmailing (silence) and Outlook (keeping my password private)?

If you want the shortest way:
System.Web.Mail.SmtpMail.SmtpServer="SMTP Host Address";
System.Web.Mail.SmtpMail.Send("from","To","Subject","MessageText");

This was code that I was reusing from another project where I wanted the send dialog to display, and for the email only to be sent when the user hit the "Send" button. For that reason, it didn't call "send"
To get the email to send silently/unattended, I just needed to add a call to "mailItem.Send()" like so:
mailItem.Importance = OlImportance.olImportanceHigh;
mailItem.Display(false);
mailItem.Send(); // This was missing

Related

How do I to use MailMessage to send mail using SendGrid?

I'm trying to send mail using SendGrid but I can't. It always throws an exception that I can't fix.
How do I to fix this issue ?
SendMail
public static Boolean isSend(IList<String> emailTo, String mensagem, String assunto, String emailFrom, String emailFromName){
try{
MailMessage mail = new MailMessage();
mail.BodyEncoding = System.Text.Encoding.UTF8;
mail.SubjectEncoding = System.Text.Encoding.UTF8;
//to
foreach (String e in emailTo) {
mail.To.Add(e);
}
mail.From = new MailAddress(emailFrom);
mail.Subject = assunto;
mail.Body = mensagem;
mail.IsBodyHtml = true;
SmtpClient smtp = new SmtpClient();
smtp.Host = CustomEmail.SENDGRID_SMTP_SERVER;
smtp.Port = CustomEmail.SENDGRID_PORT_587;
smtp.Credentials = new System.Net.NetworkCredential(CustomEmail.SENDGRID_API_KEY_USERNAME, CustomEmail.SENDGRID_API_KEY_PASSWORD);
smtp.UseDefaultCredentials = false;
smtp.EnableSsl = false;
smtp.Timeout = 20000;
smtp.Send(mail);
return true;
}catch (SmtpException e){
Debug.WriteLine(e.Message);
return false;
}
}
CustomMail
//SendGrid Configs
public const String SENDGRID_SMTP_SERVER = "smtp.sendgrid.net";
public const int SENDGRID_PORT_587 = 587;
public const String SENDGRID_API_KEY_USERNAME = "apikey"; //myself
public const String SENDGRID_API_KEY_PASSWORD = "SG.xx-xxxxxxxxxxxxxxxxxxxxxxxxx-E";
Exception
Exception thrown: 'System.Net.Mail.SmtpException' in System.dll
Server Answer: Unauthenticated senders not allowed
For sending emails with SendGrid there is v3 API. The NuGet name is SendGrid and the link is here.
This library does not work with System.Net.Mail.MailMessage, it uses SendGrid.Helpers.Mail.SendGridMessage.
This library uses an API key for authorization. You can create one when you log into SendGrid web app, and navigate to Email API -> Integration Guide -> Web API -> C#.
var client = new SendGridClient(apiKey);
var msg = MailHelper.CreateSingleTemplateEmail(from, new EmailAddress(to), templateId, dynamicTemplateData);
try
{
var response = client.SendEmailAsync(msg).Result;
if (response.StatusCode != HttpStatusCode.OK
&& response.StatusCode != HttpStatusCode.Accepted)
{
var errorMessage = response.Body.ReadAsStringAsync().Result;
throw new Exception($"Failed to send mail to {to}, status code {response.StatusCode}, {errorMessage}");
}
}
catch (WebException exc)
{
throw new WebException(new StreamReader(exc.Response.GetResponseStream()).ReadToEnd(), exc);
}
I think your problem stems from not instantiating the SMTP client with the server in the constructor. Also you should wrap your smtpclient in a using statement so it disposes of it properly, or call dispose once you're finished.
Try this:
public static Boolean isSend(IList<String> emailTo, String mensagem, String assunto, String emailFrom, String emailFromName)
{
try
{
MailMessage mail = new MailMessage();
mail.BodyEncoding = System.Text.Encoding.UTF8;
mail.SubjectEncoding = System.Text.Encoding.UTF8;
//to
foreach (String e in emailTo)
{
mail.To.Add(e);
}
mail.From = new MailAddress(emailFrom);
mail.Subject = assunto;
mail.Body = mensagem;
mail.IsBodyHtml = true;
using(SmtpClient smtp = new SmtpClient(CustomEmail.SENDGRID_SMTP_SERVER)){
smtp.Port = CustomEmail.SENDGRID_PORT_587;
smtp.Credentials = new System.Net.NetworkCredential(CustomEmail.SENDGRID_API_KEY_USERNAME, CustomEmail.SENDGRID_API_KEY_PASSWORD);
smtp.UseDefaultCredentials = false;
smtp.EnableSsl = false;
smtp.Timeout = 20000;
smtp.Send(mail)
}
}
catch (SmtpException e)
{
Debug.WriteLine(e.Message);
return false;
}
}
If that doesn't work you could try removing the port, enablessl and usedefaultcredentials parameters for the smtp client. I use sendgrid all the time and don't use those options.
To more specifically answer your original question and the cause of your exception, the SendGrid SMTP server probably isn't looking for your account's username and password, but rather your API key. The error seems to indicate your authentication is not successful.
https://sendgrid.com/docs/for-developers/sending-email/v3-csharp-code-example/
To integrate with SendGrids SMTP API:
Create an API Key with at least "Mail" permissions.
Set the server host in your email client or application to smtp.sendgrid.net.
This setting is sometimes referred to as the external SMTP server or the SMTP relay.
Set your username to apikey.
Set your password to the API key generated in step 1.
Set the port to 587.
Using the SendGrid C# library will also simplify this process:
https://sendgrid.com/docs/for-developers/sending-email/v3-csharp-code-example/
// using SendGrid's C# Library
// https://github.com/sendgrid/sendgrid-csharp
using SendGrid;
using SendGrid.Helpers.Mail;
using System;
using System.Threading.Tasks;
namespace Example
{
internal class Example
{
private static void Main()
{
Execute().Wait();
}
static async Task Execute()
{
var apiKey = Environment.GetEnvironmentVariable("NAME_OF_THE_ENVIRONMENT_VARIABLE_FOR_YOUR_SENDGRID_KEY");
var client = new SendGridClient(apiKey);
var from = new EmailAddress("test#example.com", "Example User");
var subject = "Sending with SendGrid is Fun";
var to = new EmailAddress("test#example.com", "Example User");
var plainTextContent = "and easy to do anywhere, even with C#";
var htmlContent = "<strong>and easy to do anywhere, even with C#</strong>";
var msg = MailHelper.CreateSingleEmail(from, to, subject, plainTextContent, htmlContent);
var response = await client.SendEmailAsync(msg);
}
}
}

converting to system.net.mail.mailMessage error

i'm actually trying to create registration page with verfication mail using MVC in visual studio, but here to send a message im getting
error : 'RandLform.Controllers.MailMessage' to 'System.Net.Mail.MailMessage' RandLform
public void SendVerficationLinkEmail(string emailID, string activationCode)
{
var VerifyUrl = "/User/VerifyAccount/" + activationCode;
var link = Request.Url.AbsoluteUri.Replace(Request.Url.PathAndQuery, VerifyUrl);
var fromEmail = new MailAddress("lokeshkingdom4u#gmail.com", "Lokesh Pladugula");
var toEmail = new MailAddress(emailID);
var fromEmailPassword = "paisa007";
string subject = "Account created Succesfully!";
string body = "<br/>To verify your account, click on below link.<br/><br/> "+" "+link+"";
var smtp = new SmtpClient
{
Host = "smtp.gmail.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NewNetworkCredential(fromEmail.Address, fromEmailPassword)
};
using (var message = new MailMessage(fromEmail, toEmail)
{
Subject = subject,
Body = body,
IsBodyHtml = true
})
smtp.Send(message);
}
Lokesh Paladugula,
I recommend you to change password of your email account.
I'm not sure if this is actual error, please send proper error.

Sending html page as message body of email in asp.net c#

I have written the below code to send an email wherein the message body is a html page.
I don't get any error when i run this code but do not get any mail. I tried putting body as simple message string then i received the email but not as message body as html page.
What is going wrong? please help.
protected void btnSend_Click(object sender, EventArgs e)
{
SendHTMLMail();
}
public void SendHTMLMail()
{
//var path = Server.MapPath("~/test/HTMLPage.htm");
StreamReader reader = new StreamReader(Server.MapPath("~/expo_crm/test/HTMLPage.htm"));
string readFile = reader.ReadToEnd();
string myString = "";
myString = readFile;
SmtpClient smtp = new SmtpClient
{
Host = "mail.abc.com", // smtp server address hereā€¦
Port = 25,
EnableSsl = false,
DeliveryMethod = SmtpDeliveryMethod.Network,
Credentials = new System.Net.NetworkCredential("abc#xyz.com", "xxxx"),
Timeout = 30000,
};
MailMessage message = new MailMessage("abc#xyz.com", "akshata#gmail.com", " html ", myString);
message.IsBodyHtml = true;
smtp.Send(message);
}
Most of the time mail server checks the html content and marks as SPAM mail based on the html tags like links, images etc in the mail. Make sure that you have low number of HTML tags probably no external links, images and try again to send mail.
Here is working code, if this helps
public void SendEmail(ListDictionary email)
{
try
{
var msg = new MailMessage {From = new MailAddress(_emailUsername, _emailFrom), BodyEncoding = Encoding.UTF8, Subject = Convert.ToString(email["SUBJECT"]), Priority = MailPriority.Normal};
//
var emailTo = (List<string>) email["TO"];
var emailCc = (List<string>) email["CC"];
var emailBcc = (List<string>) email["BCC"];
foreach (var to in emailTo.Where(to => to.Length > 1))
msg.To.Add(to);
foreach (var cc in emailCc.Where(cc => cc.Length > 1))
msg.CC.Add(cc);
foreach (var bcc in emailBcc.Where(bcc => bcc.Length > 1))
msg.Bcc.Add(bcc);
//
msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(Convert.ToString(email["BODY_TEXT"]), Encoding.UTF8, "text/plain"));
msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(Convert.ToString(email["BODY_HTML"]), Encoding.UTF8, "text/html"));
//
new SmtpClient
{
Credentials = new NetworkCredential(_emailUsername, _emailPassword),
DeliveryMethod = SmtpDeliveryMethod.Network,
EnableSsl = true,
Host = "smtp.gmail.com"
}.Send(msg);
}
catch (Exception e)
{
L.Get().Fatal("Failed", e);
}
}
Could it be that you're setting the body before you set it to Html?
Worth trying using the full object constructor (new MailMessage(){ IsBodyHtml = true, Body = myString}) or setting the properties one at a time to make sure...

SendAsync Smtp Mail Error

Application requires that a use SendAsync rather than just Send. So i Made a Class CEmailServer and set up everything. So far Send works fine but when changing it to work with SendAsync it does not. I Created a Method to be called when a mail is sent and the userToken is in place but it keeps failing. i Can't find my error. Here is my code :
static bool mailSent = false;
//Method for Sending with attachment.
public void SendEmail(string Address, string Recipient, string Subject, string Body, string Dir)
{
var fromAddress = new MailAddress("someadress.kimberley#gmail.com", "My Company");
var toAddress = new MailAddress(Address, Recipient);
const string fromPassword = "password";
string subject = Subject;
string body = Body;
var smtp = new SmtpClient
{
Host = "smtp.gmail.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
};
using (var message = new MailMessage(fromAddress, toAddress)
{
Subject = subject,
Body = body,
})
{
smtp.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
string userState = "Test";
message.Attachments.Add(new Attachment(Dir));
smtp.SendAsync(message,userState);
message.Dispose();
}
}
//Method for Sending regular message without attachment.
public void SendEmail(string Address, string Recipient, string Subject, string Body)
{
var fromAddress = new MailAddress("someadress.kimberley#gmail.com", "My Company");
var toAddress = new MailAddress(Address, Recipient);
const string fromPassword = "password";
string subject = Subject;
string body = Body;
var smtp = new SmtpClient
{
Host = "smtp.gmail.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
};
using (var message = new MailMessage(fromAddress, toAddress)
{
Subject = subject,
Body = body,
})
{
smtp.SendCompleted += new SendCompletedEventHandler(SendCompletedCallback);
string userState = "Message Sent";
smtp.SendAsync(message, userState);
message.Dispose();
}
}
//Method to be called when sending is complete
private static void SendCompletedCallback(object sender, AsyncCompletedEventArgs e)
{
// Get the unique identifier for this asynchronous operation.
String token = (string)e.UserState;
if (e.Cancelled)
{
MessageBox.Show("Sending Canc");
}
if (e.Error != null)
{
MessageBox.Show("Error Sending Mail");
}
else
{
MessageBox.Show("Message sent.");
}
mailSent = true;
}
Thank you very much!
You are disposing the message before the send can complete. You should be disposing them in the SendCompleted callback event. Here's an example of the best way to dispose the client and the message.
Your code should look something like this:
var smtp = new SmtpClient
{
Host = "smtp.gmail.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
};
var message = new MailMessage(fromAddress, toAddress)
{
Subject = subject,
Body = body,
};
smtp.SendCompleted += (s, e) => {
SendCompletedCallback(s, e);
smtp.Dispose();
message.Dispose();
};
string userState = "Test";
message.Attachments.Add(new Attachment(Dir));
smtp.SendAsync(message, userState);

SmtpClient cannot send email

I try two application, one in java and one in C#. The java application can send email successfully but the C# cannot. Here is the two apps :
1.Java
final String username = "myaccount#mydomain";
final String password = "mypassword";
String smtpHost = "smtp.mydomain";
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.host", smtpHost);
props.put("mail.smtp.port", "465");
props.put("mail.smtp.socketFactory.port", "465");
props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() {
#Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(username));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(username));
message.setSubject("Test send email");
message.setText("Hi you!");
Transport.send(message);
2.C#
string username = "myaccount#mydomain";
string password = "mypassword";
string smtpHost = "smtp.mydomain";
SmtpClient mailClient = new SmtpClient(smtpHost, 465);
mailClient.Host = smtpHost;
mailClient.Credentials = new NetworkCredential(username, password);
mailClient.EnableSsl = true;
MailMessage message = new MailMessage(username, username, "test send email", "hi u");
mailClient.Send(message);
So, what is the mistake i made in C# application? Why it cannot send email?
EDIT:
I have read this question How can I send emails through SSL SMTP with the .NET Framework? and it works. The deprecated System.Web.Mail.SmtpMail works but System.Net.Mail.SmtpClient doesn't. Why ?
3.This C# code work fine :
System.Web.Mail.MailMessage myMail = new System.Web.Mail.MailMessage();
myMail.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserver","smtp.mydomain");
myMail.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpserverport","465");
myMail.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusing","2");
myMail.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpauthenticate", "1");
myMail.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendusername", "myaccount#mydomain");
myMail.Fields.Add("http://schemas.microsoft.com/cdo/configuration/sendpassword", "mypassword");
myMail.Fields.Add("http://schemas.microsoft.com/cdo/configuration/smtpusessl", "true");
myMail.From = "myaccount#mydomain";
myMail.To = "myaccount#mydomain";
myMail.Subject = "new code";
myMail.BodyFormat = System.Web.Mail.MailFormat.Html;
myMail.Body = "new body";
System.Web.Mail.SmtpMail.SmtpServer = "smtp.mydomain:465";
System.Web.Mail.SmtpMail.Send(myMail);
The .NET System.Net.Mail.SmtpClient class cannot handle implicit SSL connection. Implicit SSL connections are sent over Port 465, as the client is configured in your example.
You can use a third party library like AIM (Aegis Implicit Mail) to send implicit SSL messages.
You can try this code as well. Also sends the email in a seperate thread.
using System.Net.Mail;
public static void Email(string Content, string To, string Subject, List<string> Attach = null, string User = "sender#sender.com", string Password = "MyPassword", string Host = "mail.sender.com", ushort Port = 587, bool SSL = false)
{
var Task = new System.Threading.Tasks.Task(() =>
{
try
{
MailMessage Mail = new MailMessage();
Mail.From = new MailAddress(User);
Mail.To.Add(To);
Mail.Subject = Subject;
Mail.Body = Content;
if (null != Attach) Attach.ForEach(x => Mail.Attachments.Add(new System.Net.Mail.Attachment(x)));
SmtpClient Server = new SmtpClient(Host);
Server.Port = Port;
Server.Credentials = new System.Net.NetworkCredential(User, Password);
Server.EnableSsl = SSL;
Server.Send(Mail);
}
catch (Exception e)
{
MessageBox.Show("Email send failed.");
}
});
Task.Start();
}

Categories

Resources