I wrote a small command line utility in C# that sends an email as a result of actions that it takes. The email is sent successfully when it is run manually from the command line, but it doesn't send when its run as a scheduled task. I set it to run with the highest user settings as a scheduled task. There are no firewall settings that would block outgoing emails on the test machine.
Do scheduled tasks run as a user that is restricted from sending emails? I'm not sure if there is any code for sending emails in C# that can set the mailer as an administrator.
Thanks.
Here is the C# code I use for sending an email:
public static void SendNotifications ()
{
string smtpServer = "mailserver.com";
string smtpUser = "a#b.com";
string smtpPassword = "abc123";
// Set the variables for the mail object.
using (MailMessage Email = new MailMessage ())
{
Email.IsBodyHtml = true;
Email.From = new MailAddress (smtpUser);
Email.To.Add ("a1#b.com");
Email.CC.Add ("a2#b.com");
Email.Subject = "Subject";
Email.Body = #"Here is a notification.";
SmtpClient smtp = new SmtpClient (smtpServer);
System.Net.NetworkCredential SMTPUserInfo = new System.Net.NetworkCredential (smtpUser, smtpPassword);
smtp.UseDefaultCredentials = false;
smtp.Credentials = SMTPUserInfo;
try
{
// Send the mail.
smtp.Send (Email);
} // try
catch (Exception ex)
{
// ignore error message
} // catch (Exception e)
} // using (MailMessage Email = new MailMessage ())
}
Assuming you're running the console application via Task Scheduler, one can change the user which runs the scheduler to one which has permission to send email. If you're using DefaultCredentials = true in your code, then this is especially important.
Typically this is done by creating a service account with sufficient permissions to perform the task at hand and nothing more. One can configure which user account will execute the task on the General tab of the task in question within the Task Scheduler. There will be a Change User button. Be sure to check "Run whether the user is logged on or not".
Related
I need to be able to send automatic emails to any users who have registered new accounts, changed passwords, and/or created new orders.
I've been given the SendEmail file, which belongs in the "Utilities" folder in my solution.
using System;
using System.Net.Mail;
using System.Net;
namespace SendEmail
{
public static class EmailMessaging
{
public static void SendEmail(String toEmailAddress, String emailSubject, String emailBody)
{
//Create a variable for YOUR TEAM'S Email address
//This is the address that will be SENDING the emails (the FROM address)
String strFromEmailAddress = "email#gmail.com";
//This is the password for YOUR TEAM'S "fake" Gmail account
String strPassword = "Password";
//This is the name of the business from which you are sending
//TODO: Change this to the name of the company you are creating the website for
String strCompanyName = "Team Final Project";
//Create an email client to send the emails
//port 587 is required to work, do not change it
var client = new SmtpClient("smtp.gmail.com", 587)
{
UseDefaultCredentials = false,
//This is the SENDING email address and password
//This will be your team's email address and password
Credentials = new NetworkCredential(strFromEmailAddress, strPassword),
EnableSsl = true
};
//Add anything that you need to the body of the message
//emailBody is passed into the method as a parameter
// /n is a new line – this will add some white space after the main body of the message
//TODO: Change or remove the disclaimer below
String finalMessage = emailBody + "\n\n Thank you, come back again soon!";
//Create an email address object for the sender address
MailAddress senderEmail = new MailAddress(strFromEmailAddress, strCompanyName);
//Create a new mail message
MailMessage mm = new MailMessage();
//Set the subject line of the message (including your team number)
mm.Subject = "Team ## - " + "Thank you!";
//Set the sender address
mm.Sender = senderEmail;
//Set the from address
mm.From = senderEmail;
//Add the recipient (passed in as a parameter) to the list of people receiving the email
mm.To.Add(new MailAddress(toEmailAddress));
//Add the message (passed)
mm.Body = finalMessage;
//send the message!
client.Send(mm);
}
}
}
My problem is that neither I nor my team members know how to implement call this from the controller in a way that will be sent automatically and with the user's email and name. We imagine they will be in the Account and Orders controllers. The accounts controller has the register and change password methods, which work, and the orders controller has the complete order method.
Also, we are not using a confirmation view, it has to be an automatic email.
We need some direction in figuring out where exactly we need to call the method from and how.
The most helpful thing I've found on the internet today is this block of code for a test message that is not intended to be sending automatic emails.
public static void CreateTestMessage(string server)
{
MailAddress from = new MailAddress("sender#gmail.com", "Team Project");
MailAddress to = new MailAddress("reciever#gmail.com", "Customer");
MailMessage message = new MailMessage(from, to);
message.Subject = "Password Changed";
message.Body = #"This is a confirmation email that your password has been changed.";
SmtpClient client = new SmtpClient(server);
client.Credentials = CredentialCache.DefaultNetworkCredentials;
try
{
client.Send(message);
}
catch (Exception ex)
{
Console.WriteLine("Exception caught in CreateBccTestMessage(): {0}",
ex.ToString());
}
}
Everything is being coded on MS VS
First create a service for EmailService and put SendEmailAsync Method in it
and call this method on your Controller.
In Method body:
1-Create your message:
var mm = new MailMessage()
2-Then you should build your smtp:
using var smtpClient = new SmtpClient();
3-Then connect it to your server
await smtpClient.ConnectAsync(
"your host",
"port",
SecureSocketOptions.SslOnConnect);
4-Now send your Email:
await smtpClient.SendAsync(mm);
5-Make sure that disconnect from your client:
await smtpClient.DisconnectAsync(true);
Note: It may give you an Exception while Connecting or Sending your Email so don't forget try catch block.
6-For Automation you can use a EmailAccount Table with relation with your Customer Table and keep your message data in it.
for ex: body ,subject..... .
In your Contorller you have your Customer So you can get his EmailAccount from DataBase and pass EmailAccount Entity to SendEmailAsync Method.
instead of creating message in body, get it from EmailAccount Entity and then countinue the Steps.
7-Enjoy it :)
In my application I have a functionality to save and publish articles. So when I click on "Save and Publish" button three things happened:
Published articles get saved in database.
A Notification email goes to a group of users that a new articles is available.
After sending emails page get redirect to "Article Listing" page without showing any success or failure message for an email.
Now Number of users who will receive emails can vary say for e.g 10, 30 50 and so on. I want to send notification emails asynchronously so that page won't get block until all the mails doesn't go to their receptionists.
Given below is a piece of code from "PublishArticle" action method
foreach (string to in emailIds)
{
ArticleNotificationDelegate proc = Email.Send;
IAsyncResult asyncResult = proc.BeginInvoke(subject, body, to, from, cc, null, null, null);
}
Below I have defined a delegate to invoke Send method
private delegate bool ArticleNotificationDelegate (string subject, string body, string to, string from, string cc, string bcc = null);
and this is the code to send an email:
public static bool Send(string subject, string body, string to, string from, string cc, string bcc = null)
{
bool response;
MailMessage mail = new MailMessage();
MailAddress fromAddress = new MailAddress(from);
mail.To.Add(to);
if (!string.IsNullOrWhiteSpace(cc))
{
mail.CC.Add(cc);
}
if (!string.IsNullOrWhiteSpace(bcc))
{
mail.Bcc.Add(bcc);
}
mail.From = fromAddress;
mail.Subject = subject;
mail.Body = body;
mail.IsBodyHtml = true;
mail.Priority = MailPriority.High;
SmtpClient client = new SmtpClient();
try
{
client.Send(mail);
response = true;
}
catch (Exception)
{
response = false;
}
finally
{
client.Dispose();
mail.Dispose();
}
return response;
}
Although this code is working fine but still I want to know that whether my this approach is fine and will not cause any problem in future.
If there is a better approach to accomplish my objective then please suggest me.
Note: As I am using .net framework 4.0 so cannot use the new features of Asyn and await available in 4.5.
Also I had used method client.SendAsync by simply replacing the client.Send and rest of my code in above Send method was same. After this change NO mails were being send and also it did not throw any exception. So I did not go with this change.
I want to send notification emails asynchronously so that page won't get block until all the mails doesn't go to their receptionists.
That's a very dangerous approach, because ASP.NET will feel free to tear down your app domain if there are no active requests. ASP.NET doesn't know that you've queued work to its thread pool (via BeginInvoke). I recommend that you use a solution like HangFire to reliably send email.
Is it possible to send email from a server that uses smtp-relay through a .net application.
I'm using app.config to get the actual values ex server IP, and the fromadress that the email should use.
According to the IT-technician the username and password to authorize should not be needed because it uses smtp-relay. The computer that are going to send the email is on the smtp-servers list of valid computers.
Can this actually work, don't I need to specify the username/pwd?
try
{
MailMessage mail = new MailMessage();
SmtpClient SmtpServer = new SmtpClient(_smtpserver);
mail.From = new MailAddress(_fromAdress);
mail.To.Add(_toAdress);
mail.Subject = _subject;
mail.Body = _body;
mail.Priority = MailPriority.High;
SmtpServer.Port = Convert.ToInt32(_port);
SmtpServer.Credentials = new System.Net.NetworkCredential(_authUsername, _authPassword);
SmtpServer.EnableSsl = true;
SmtpServer.Send(mail);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
In your snippet you are specifying credentials
SmtpServer.Credentials = new System.Net.NetworkCredential(_authUsername, _authPassword);
You can remove that line and it still will work if SMTP relay is configured as you said.
in your case,if you are seting your username and password in webconfig even then you need to call it like above.
but if you using your default mail credentials then it will pick automatically..
and if you are using diiferent mail client for sender then you have to pass credentials..
I had same situation. I got same error code. I noticed , I had used system.web.mail. But my application is a console application. I changed library, I used system.net.mail. And it works now.
I am developing an application for sending email using SmtpClient, works very well, but I have a question about user authentication, because the codes that I saw, you can only know if e-mail and password are correct when e-mail is sent.
Is there any way to do this authentication before. I am using this piece as an example:
public void SendMessage()
{
MailMessage mensagem = new MailMessage();
mensagem.From = new MailAddress(email);
mensagem.To.Add(txtto.Text);
mensagem.Subject = txtsubject.Text;
mensagem.Body = richMessage.Text;
SmtpClient smtp = new SmtpClient();
if (Form1.servidor.Equals("hotmail.com"))
{
smtp.Host = "smtp.live.com";
smtp.Port = 25;
smtp.EnableSsl = true;
}
smtp.Credentials = new System.Net.NetworkCredential(email, Form1.password);
//only in this line is actually verified the existence of the user + password
smtp.Send(mensagem);
}
I don't wanna need send message to know if user+password is correct. Anybody knows someway, maybe another namespace...
thanks.
You could use impersonation, e.g. with this the small impersonation class to try to log in a Windows user.
I.e. place the following using block around your code to run under the other user account:
using ( new Impersonator( "myUsername", "myDomainname", "myPassword" ) )
{
...
<code that executes under the new context>
...
}
You could try...catch around the using block to check for wrong password, or, better, use the function inside the Impersonator's source to login and check the result, i.e. without catching (performance).
How would I tell my application to send an email to a subscriber? How would I send it every week starting from the time the appication is launched.
Use the classes in the System.Net.Mail namespace to send emails from your app. Specifically, the MailMessage class serves this purpose.
To send emails periodically, you can use a timer (use System.Timers.Timer, for example) or you could use the built-in Windows task scheduler, which has rich functionality and runs as a service, so that you don't need to keep an interactive session open on your machine. I can give you a more detailed answer if you provide more details about the type of app you're developing.
I use this method to use gmail, and it works well for me.
var fromAddress = new MailAddress("From");
var toAddress = new MailAddress("To");
string fromPassword = textBox4.Text;
const string subject = "Test";
const string body = "Test Finished";
var smtp = new SmtpClient
{
Host = "smtp.gmail.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new System.Net.NetworkCredential(fromAddress.Address, fromPassword)
};
using (var message = new MailMessage(fromAddress, toAddress)
{
Subject = subject,
Body = body
})
{
Attachment attachf = new Attachment("C:\\file.txt");
message.Attachments.Add(attachf);
smtp.Send(message);
}
}
I haven't created anything directly like this myself but I've seen solutions that use a Scheduled Task on the Server which are set to run on a certain date/time a small script that carries out what is required. This assumes you have your own server though...