I'm developing a console app which will be executed from a windows service that needs to send emails using the domain account associated to the domain account running the windows service.
In my development machine I'm logged with a domain account that belongs to the same domain that will run the windows service but I'm not able to get it working properly.
For this development I'm using .NET 4.6.1 and the nuget package FluentEmail.Smtp
My code looks like this:
Email.DefaultSender = new SmtpSender(new SmtpClient
{
UseDefaultCredentials = true,
EnableSsl = true,
Host = "smtp.office365.com",
TargetName = "STARTTLS/smtp.office365.com",
Port = 587,
DeliveryMethod = SmtpDeliveryMethod.Network
});
await Email.From("myname#mycompanydomain.com", "Some tittle")
.To(emailListObject)
.Subject("Some subject")
.Body("Some body", true)
.SendAsync();
With this code I'm getting the following exception:
Unable to connect to the remote server
A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond 52.96.9.178:587
at System.Net.Mail.SmtpConnection.ConnectAndHandshakeAsyncResult.End(IAsyncResult result)
at System.Net.Mail.SmtpTransport.EndGetConnection(IAsyncResult result)
at System.Net.Mail.SmtpClient.ConnectCallback(IAsyncResult result)
Note: From my machine I'm able to ping the IP mentioned in the exception
I'll appreciate your assistance
For starters you might want to take a look at the official document - direct send. You will note that there are quite a few issues (such as TLS security) alongside proper configuration of your Exchange server.
Without more information in your question it is rather limited as to what can be answered, however as an alternate solution, maybe take a look at direct send. (which is much less effort).
Settings for direct send
Enter the following settings on the device or in the application directly.
Server/smart host. Use your MX endpoint, for example, contoso-com.mail.protection.outlook.com
Port. Use port 25
TLS/StartTLS. Enable this.
Email address. Use any email address for one of your Office 365 accepted domains. This email address does not need to have a mailbox.
Microsoft recommends adding an SPF record to avoid having messages flagged as spam. If you are sending from a static IP address, add it to your SPF record in your domain registrar's DNS settings as follows:
DNS entry Value
SPF v=spf1 ip4:<Static IP Address> include:spf.protection.outlook.com ~all
Related
I have implemented FTP code with use of WinSCP .NET assembly and hosted it on an Azure AppService.
It works locally and on Azure.
But in very few random times, when hosted on Azure, it throws the following error:
Error transferring file 'D:\local\Temp\test_settings.txt'. Server sent passive reply with unroutable address 10.YYY.YYY.YYY, using host address instead. Copying files to remote side failed. Rejected data connection for transfer of "/test_settings.txt", IP addresses of control and data connection do not match
Since the IP starts with 10. does that mean that it's local in the FTP server's network?
Can I do something to improve the implementation?
Do you think that the solution will have a problem when used concurrently by multiple requests?
My code is a copy of the Simple C# example with the following settings:
SessionOptions sessionOptions = new SessionOptions
{
Protocol = Protocol.Ftp,
UserName = username,
Password = password,
GiveUpSecurityAndAcceptAnyTlsHostCertificate = true,
FtpSecure = FtpSecure.Explicit,
HostName = 'ftp.domain.com'
};
IP addresses of control and data connection do not match
That's a message from FileZilla FTP server. It's a security measure. It might indicate that external IP address of your app service instance changed mid transfer. Or of course, it might indicate that you connection was hijacked (that's what the server tries to detect).
It has nothing to do with WinSCP.
I do not know if the IP address of the Azure app service can be fixed somehow. If not, all you can do is to reconnect and retry the transfer. I believe you would have the same problem with any FTP client. Maybe with IPv6 connection, the problem would not happen. But I'm not sure, it's just a wild guess. Though you cannot force IPv6 with WinSCP (only by disabling IPv4 altogether, but I do not know if that's even possible with the app service).
Despite spending an entire morning with GoDaddy chat, and reading almost everything I can find on sending emails via godaddy I am still no closer to solving my issue.
What Have I tried
Firstly, this is my code.
var smtpClient = new SmtpClient("smtpout.secureserver.net")
// var smtpClient = new SmtpClient("relay-hosting.secureserver.net", 25)
{
Port = 25,
UseDefaultCredentials = false,
EnableSsl = false,
Credentials = new NetworkCredential("user#User.com", "Password#"),
// DeliveryMethod = SmtpDeliveryMethod.Network,
};
and I think I should mention that this works when I attempt to use google's free smpt server, the mail is sent. However using my godaddy credentials, I get the following error,
Message = "Service not available, closing transmission channel. The server response was: Cannot connect to SMTP server 72.167.234.197 (72.167.234.197:25), connect error 10060" other times it says
InnerException = {"Unable to read data from the transport connection: An established connection was aborted by the software in your host machine."}
I have also tried other suggested ports like 587 , 80, 3552. Nothing has changed, I have also tried the suggestion at this link https://www.godaddy.com/help/send-email-using-systemnetmail-19291 . Which did not work (no suprise to me, cause where am i putting the account password) . Would appreciate it if anyone has solved getting their C# application to work with Godaddy. Like I said it works with Google so I dont believe my code is an issue in anyway.
regards
Your code looks good, however, one way to test if you are using the correct smtp settings is to send the email with a program like Microsoft Outlook or Thunderbird. Also, if you are using a dedicated server or a VPS, you need to use
dedrelay.secureserver.net
See: https://in.godaddy.com/help/what-is-my-servers-email-relay-server-16601
Also, check out this see: https://in.godaddy.com/community/VPS-Dedicated-Servers/Unable-to-send-email-from-C-net-application-from-website/m-p/102913#M1256
which mentions: "If you are using a Plesk shared hosting plan, use relay-hosting.secureserver.net and port 25. Do not specify a username or password. Other relay/smtp servers will not work from our shared hosting."
we are having 2 cloud services hosted on Azure.
Both the services depend on our smtp server for sending mails.
Problem is azure cloud service not able to connect to our smtp server.
we are able to use same code on internal machines without any issue. also we had checked that 25 port is open and IP address are also not on blacklist.
Below is the error while connecting from cloud service :
A connection attempt failed because the connected party did not
properly respond after a period of time, or established connection
failed because connected host has failed to respond 111.93.111.42:25
Email sending logic
MailMessage message = new MailMessage(senderID, reminder.UserName, template.Subject, body);
message.From = new MailAddress(data.SenderEmail, data.SenderName);
message.IsBodyHtml = true;
try
{
SmtpClient smtp = new SmtpClient
{
Host = data.SMTPServer, // smtp server address here...
Port = data.PortNo,
EnableSsl = data.SSL,
DeliveryMethod = SmtpDeliveryMethod.Network,
Credentials = new System.Net.NetworkCredential(senderID, senderPassword),
Timeout = 30000,
};
smtp.Send(message);
//Thread th = new Thread(() => { smtp.Send(message); });
//th.Start();
}
catch (Exception ex)
{
ErrorLogging.ErrorLog(ex, "Error Reminders send Mail - Employee Reminders Mail Error Message : " + ex.Message, "Employee Reminders Mail", "0", "EmployeeRemindersMail", schemaName, companyId);
}
Microsoft recommends that Azure customers employ authenticated SMTP relay services (typically connected via TCP port 587 or 443, but often support other ports too) to send e-mail from Azure VMs or from Azure App Services. These services specialize in sender reputation to minimize the possibility 3rd party e-mail providers will reject the message. Such SMTP relay services include but are not limited to SendGrid. It is also possible you have a secure SMTP relay service running on premises that can be used.
Use of these e-mail delivery services is in no way restricted in Azure regardless of subscription type.
Reference: https://blogs.msdn.microsoft.com/mast/2017/11/15/enhanced-azure-security-for-sending-emails-november-2017-update/
You may also want to refer this thread which addresses similar issue and see if that helps.
Please note - from the article linked to above - Enterprise Azure clients CAN send SMTP messages direct from Azure:
"For Enterprise Agreement Azure users, there's no change in the technical ability to send email without using an authenticated relay. Both new and existing Enterprise Agreement users can try outbound email delivery from Azure VMs directly to external email providers without any restrictions from the Azure platform. Although it's not guaranteed that email providers will accept incoming email from any given user, delivery attempts won't be blocked by the Azure platform for VMs within Enterprise Agreement subscriptions. You'll have to work directly with email providers to fix any message delivery or SPAM filtering issues that involve specific providers."
In Windows you can configure the mail settings from the control panel. What I want to know is where is that information stored? I need to write an app that can send email and by default I want to use those settings. I assumed that if I used the parameterless constructor of SmtpClient it would read them, however when I run the following code:
var smtp = new SmtpClient();
var host = smtp.Host;
var port = smtp.Port;
Console.WriteLine("{0}:{1}", host,port);
I get the host as null (though the port is 25.) If I send a message through it, it throws an exception saying "Host not specified".
Where can I get this pre-configured data?
You need to set the property first before checking for its value otherwise it will be null. However, by default, the port is 25. That's why you see 25 for port even though none was specified. Here's the definition of Host property of SmtpClient object.
public string Host { set; get; }
Member of System.Net.Mail.SmtpClient
Summary:
Gets or sets the name or IP address of the host used for SMTP transactions.
Returns:
A System.Strin
g that contains the name or IP address of the computer to use for SMTP transactions.
Try this...
var smtp = new SmtpClient();
smtp.Host = "localhost"; //your mail server host name or ip address
var host = smtp.Host;
var port = smtp.Port;
Console.WriteLine("{0}:{1}", host,port);
Usually you would need the SMTP server name before hand and use this info as part of your configuration in your program. You can have the user obtains this information from outlook settings. I assuming you already know this. For whatever reasons you want to get the SMTP server name dynamically, this activity may be viewed as hacking and can pose a security issue to the user. Can you image if some programs automatically use your mail server pre-configured in outlook to send our some emails?
With that said, one way to achieve this is to have a 3rd party port scanner as part of your process to get a list of potential SMTP server names and use the helo command to verify SMTP existence. This should help determine which ip is the SMTP server.
When you search on web you will find very easy answers for "How to read emails programmatically"... Al the websites are explaining most of the same like this page.
http://omegacoder.com/?p=454
// depends from Exchange server version
service.Credentials = new NetworkCredential("MDR", "password", "zzz");
service.AutodiscoverUrl("mdr#zzz.be");
object o = service.FindItems(WellKnownFolderName.Inbox, new ItemView(10));
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.Inbox, new ItemView(10));
foreach (Item item in findResults.Items)
{
Console.WriteLine(item.Subject);
}
it fails when it executes the autodiscoverURL line. The error says "The Autodiscover service couldn't be located."
So I googled further and found this site from Microsoft https://www.testexchangeconnectivity.com/#&&/wEXAQUBcwUBME93h2+JjI0+MV2gTqcRL0g43z9m Here you can test your mail server....
When I pass the parameters I get the error below....
But I still don't understand what the problem is? Do I need to add a record to DNS ? Can someone help?
Attempting to test potential Autodiscover URL https://autodiscover.zzz.be/AutoDiscover/AutoDiscover.xml
Testing of this potential Autodiscover URL failed.
Test Steps
Attempting to resolve the host name autodiscover.ncb.be in DNS.
The host name resolved successfully.
Additional Details
IP addresses returned: 213.246.192.205
Testing TCP port 443 on host autodiscover.ncb.be to ensure it's listening and open.
The specified port is either blocked, not listening, or not producing the expected response.
Tell me more about this issue and how to resolve it
Additional Details
A network error occurred while communicating with the remote host.
Exception details:
Message: No connection could be made because the target machine actively refused it 213.246.192.205:443
Type: System.Net.Sockets.SocketException
Stack trace:
at System.Net.Sockets.TcpClient.Connect(String hostname, Int32 port)
at Microsoft.Exchange.Tools.ExRca.Tests.TcpPortTest.PerformTestReally()
Attempting to contact the Autodiscover service using the HTTP redirect method.
The attempt to contact Autodiscover using the HTTP Redirect method failed.
Test Steps
Attempting to resolve the host name autodiscover.zzz.be in DNS.
The host name resolved successfully.
Additional Details
IP addresses returned: 213.246.192.205
Testing TCP port 80 on host autodiscover.zzz.be to ensure it's listening and open.
The port was opened successfully.
ExRCA is checking the host autodiscover.zzz.be for an HTTP redirect to the Autodiscover service.
ExRCA failed to get an HTTP redirect response for Autodiscover.
Additional Details
A Web exception occurred because an HTTP 404 - NotFound response was received from IIS7.
Attempting to contact the Autodiscover service using the DNS SRV redirect method.
ExRCA failed to contact the Autodiscover service using the DNS SRV redirect method.
Test Steps
Attempting to locate SRV record _autodiscover._tcp.ncb.be in DNS.
The Autodiscover SRV record wasn't found in DNS.
Tell me more about this issue and how to resolve it
You don't necessarily need to use the autodiscovery if you already know the address of your exchange server. Try the following instead (for more info, look here:
service.Url = new Uri("https://hostname/EWS/Exchange.asmx");
Replace "hostname" with the hostname for your exchange server.
I hope you should have the solution by this time now. This is just to help anyone bumped on this post.
I found the solution on one of the technet article, I twick to suite me, and is working fine for me.
Just replace the line in your code with following:
service.AutodiscoverUrl("user#yourdomain.com",
delegate
{
return true;
});
I had some other issues but not related to this bit though.
Happy Coding,
Sanjay.
I had the same issue with AutoDiscover. It's not necessary, you can specify your URL like
Uri myUri = new Uri("https://Hostname/ews/exchange.asmx");
userData.AutodiscoverUrl = myUri;
service.Url = myUri;
As the hostname you can put the Server IP address like 192.168.100.10
Alternatively, to find what your Exchange server hostname is (in in fact the whole url to use) if you are using Outlook, go to your computer start bar, where the Date and time is showing, you will find the Outlook icon, hold Ctrl + right click on the outlook icon and click “Test Email Auto Configuration”
Check the "Use AutoDiscover" checkbox. Enter an email address hosted on that Exchange Server along with its password and you will recieve a bunch of url's. Use the 1 that says "Availability Service URL"
Consider that the credentials being passed need to have permission to the given exchange mailbox / server. In my case using a different set of credentials that are properly permissioned works but not for a service account which I'm trying to get to work.
Once I discover what exactly the account needs to be permissioned for I will update it here.
Update: My issue was the service account was from a domain different than the domain on which the exchange 2007 instance is running, even though there is a trust relationship between the two. I found this is a documented known issue in Exchange 2007 in how it looks up accounts in its forest. In the end had to create an identical service account (name/pass) on the domain on which the exchange server is sitting and specify username as {exchange_domain}{service_account_name}. The windows service that calls EWS runs as {original_domain}{service_account_name}.
For reference, the exception was:
Microsoft.Exchange.WebServices.Data.ServiceResponseException:
Failed to get valid Active Directory information for the calling account. Confirm that it is a valid Active Directory account.