How to use Microsoft.Exchange.WebServices? - c#

i try to use : Microsoft.Exchange.WebServices.dll to use outlook. but connection return error
Error return line:service.AutodiscoverUrl("myusernamek#xxxx.com");
The Autodiscover service could not be located. my codes:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Mail;
using System.Net;
using Microsoft.Exchange.WebServices.Data;
using Microsoft.Exchange.WebServices.Autodiscover;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
namespace test
{
class Program
{
static void Main(string[] args)
{
try
{
// Connect to Exchange Web Services as user1 at contoso.com.
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.Credentials = new WebCredentials("myusernamek#xxxx.com", "mypassword", "xxxx.com");
service.TraceEnabled = true;
service.AutodiscoverUrl("myusernamek#xxxx.com");
// Create the e-mail message, set its properties, and send it to user2#contoso.com, saving a copy to the Sent Items folder.
EmailMessage message = new EmailMessage(service);
message.Subject = "Interesting";
message.Body = "The proposition has been considered.";
message.ToRecipients.Add("recipientname#xxxx.aero");
message.SendAndSaveCopy();
// Write confirmation message to console window.
Console.WriteLine("Message sent!");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("Error: " + ex.Message);
Console.ReadLine();
}
}
}
}

I know this is an old question, but recently wrestled with this and similar looking error (including ISA server). It was fixed with:
service.EnableScpLookup = false;
This was not required when working with an explicit URL, but was when using AutoDiscover

This is a common problem , Autodiscover service error is encountered when this autodiscover service by exchange is down
Resolution is to provide actual URL for exchange location , rather than autodiscovering it.
This solved my same issue.

The code suggest that you have an Exchange 2007 server... Is it properly configured for using the Autodiscover features? Confirm that you can ping autodiscover.XXXX.com and view https://autodiscover.XXXX.com in a web browser.
Alternately, you may need to use your internal domain name for autodiscovery and login. For example, in my office the external email addresses are on a domain like CompanyX.com, but the internal Active Directory domain is like CompanyX.local, and we do not have autodiscover on the open Internet, so my EWS needs to locate Autodiscover.CompanyX.local.

this is an old post but maybe someone will need it.
do not use auto discover, it is rly slow.
how to find your exchange url:
-open your outlook application and connect to your exchange
-hold Ctrl key and right click on the outlook icon in the system tray
-select "test e-mail auto configuration"
-click the test button
-look for the following line:
oh and to use the url you trop that extra line of code:
service.Url = new Uri("your url here");

try these concept:
private static ExchangeService getService(String userEmail, String login, String password, String hostName)
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010);
AutodiscoverService auservice = new AutodiscoverService(hostName);
if (auservice.ServerInfo != null)
{
try
{
service.AutodiscoverUrl(userEmail, RedirectionUrlValidationCallback);
}
catch (AutodiscoverRemoteException ex)
{
Console.WriteLine("Exception thrown: " + ex.Error.Message);
}
}
else
{
service.Url = new Uri("https://" + hostName + "/EWS/Exchange.asmx");
}
service.UseDefaultCredentials = true;
if (service.ServerInfo == null)
{
service.Credentials = new WebCredentials(login, password);
}
return service;
}

Related

Python Read Emails

My teammate uses the above code in C# (.NET) to extract email details from his inbox. If you notice it does not require any credential.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Exchange.WebServices.Data;
namespace ConsoleApplication1 {
class Program
{
static void Main(string[] args)
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.AutodiscoverUrl("FirstName.LastName#company.com", RedirectionUrlValidationCallback);
if (service != null)
{
FindItemsResults<Item> resultout = service.FindItems(WellKnownFolderName.Inbox, new ItemView(10));
foreach (Item item in resultout.Items)
{
EmailMessage message = EmailMessage.Bind(service, item.Id);
String subject = message.Subject.ToString();
Console.Write(subject);
String fromwhom = message.From.Address.ToString();
Console.Write(fromwhom);
}
}
}
private static bool RedirectionUrlValidationCallback(string redirectionUrl)
{
// The default for the validation callback is to reject the URL.
bool result = false;
Uri redirectionUri = new Uri(redirectionUrl);
// Validate the contents of the redirection URL. In this simple validation
// callback, the redirection URL is considered valid if it is using HTTPS
// to encrypt the authentication credentials.
if (redirectionUri.Scheme == "https")
{
result = true;
}
return result;
}
}
}
I need to perform the same steps but in Python. i.e read email details.
My attempt
from exchangelib import Account, Configuration, Credentials, DELEGATE, IMPERSONATION, NTLM
email = 'FirstName.LastName#company.com'
creds = Credentials(email, "")
account = Account(email, autodiscover=True, credentials = creds)
Error:
AutoDiscoverFailed: All steps in the autodiscover protocol failed
With Autodiscover false
from exchangelib import Account, Configuration, Credentials, DELEGATE, IMPERSONATION, NTLM
email = 'FirstName.LastName#company.com'
creds = Credentials(email, "")
config = Configuration(server = "domain.com", credentials=creds)
account = Account(email, autodiscover=False, config = config)
Error:
Wrong username or password for https;//domain.com/EWS/Exchange.asmx
I can access the https;//domain.com/EWS/Exchange.asmx via url, without entering any credential.
Note: I am fairly good in Python with no knowledge of C#.
I believe there are different ways of approaching authentication in Python; here's one.
I've worked on a similar project, where I try to print out an email [web automation], for which I used selenium and a webdriver to access a yahoo mail. This project included page inspection -- another approach. The code isn't optimised and the final output is not what I intended yet, but you could understand the idea at least.
Good Luck!

C# Console Application - Parsing Office 365 Inbox

I was able to succeed via a package I found called EAGetMail. Unfortunately, I realized soon after that they have a token system and this is not a free approach.
There are a couple other choices available, like using Outlook Mail REST API, and MimeKit, but I'm lost on how to achieve my end result because no "start to finish" code is available on either of these references that demonstrates how to parse an Inbox for an account.
I've started to write this with the help of Mimekit, but am not sure if this is the proper way at all.
I must imagine it looks something like:
using (var client = new SmtpClient ())
{
client.Connect("outlook.office365.com", 587);
client.Authenticate("myemail#office365account.com", "mypassword");
var message = MimeMessage.Load(stream);
}
I don't know how to setup the stream mentioned above, and I don't know if it's possible to do this with Mimekit and Office 365.
I'm open to seeing a solution for this in any other approach that's not through EAGetMail. If anyone has a lightweight solution ranging from actual establishing a connection, to pulling messages from the inbox, would be great to see!
I've got it using EWS (Exchange Web Services). Here's my code:
private static bool RedirectionUrlValidationCallback(string redirectionUrl)
{
// The default for the validation callback is to reject the URL.
bool result = false;
Uri redirectionUri = new Uri(redirectionUrl);
// Validate the contents of the redirection URL. In this simple validation
// callback, the redirection URL is considered valid if it is using HTTPS
// to encrypt the authentication credentials.
if (redirectionUri.Scheme == "https")
{
result = true;
}
return result;
}
static void Main(string[] args)
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
service.Credentials = new WebCredentials("email#myemail.com", "myPassword");
service.AutodiscoverUrl("email#myemail.com", RedirectionUrlValidationCallback);
//creates an object that will represent the desired mailbox
Mailbox mb = new Mailbox(#"email#myemail.com");
//creates a folder object that will point to inbox folder
FolderId fid = new FolderId(WellKnownFolderName.Inbox, mb);
//this will bind the mailbox you're looking for using your service instance
Folder inbox = Folder.Bind(service, fid);
//load items from mailbox inbox folder
if (inbox != null)
{
FindItemsResults<Item> items = inbox.FindItems(new ItemView(100));
foreach (var item in items)
{
item.Load();
Console.WriteLine("Subject: " + item.Subject);
}
}
}

SPUtility.SendEmail() always returns false

I have one application which will create task form for each level based on the prior level approval. While creating each tasks I have to send the email to the users who all are involved in the task. For this I am using SPUtility.SendEmail() method. But unfortunately, it didn't work so far. The debugger successfully passed through the SendEmail method without any exception. but the value will always false. The SMTP server is working for the application other than the SP Applications. My code is shown below.
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite spSite = new SPSite(SiteURL))
{
using (SPWeb spWeb = spSite.OpenWeb())
{
headers = new StringDictionary();
headers.Add("to", To);
headers.Add("from", From);
headers.Add("cc", CC);
headers.Add("bcc", BCC);
if (Priority.Equals("High"))
{
headers.Add("X-Priority", "1 (Highest)");
headers.Add("X-MSMail-Priority", "High");
headers.Add("Importance", "High");
}
headers.Add("subject", Subject);
headers.Add("content-type", "text/html");
Status = SPUtility.SendEmail(spWeb, true, true, To, Subject, Body);
}
}
});
Please help me to resolve this issue. All Suggestions would be appreciated. Thanks in advance.
I had the same problem a few minutes ago.
You might have a problem with smtp server RELAY.
Try this:
Open IIS 6.
Go To SMTP Virtual Server (Open properties)
Tab General: Select IP adddress of the server in the dropdown
Tab Access:
4.1 In Access Control ensure anonymous access is checked
4.2 In Relay Restrictions add IP: 127.0.0.1 and IP address of the server
Tab Delivery: Go to button "Outbound Connections" and set port = 587
that´s all.
I hope helpfull
It looks to me like you're using the wrong method signature. You're going to the trouble of setting up headers as a StringDictionary, but then you're using the overload of SPUtility.SendEmail() that doesn't use those headers.
Try this instead:
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite spSite = new SPSite(SiteURL))
{
using (SPWeb spWeb = spSite.OpenWeb())
{
headers = new StringDictionary();
headers.Add("to", To);
headers.Add("from", From);
headers.Add("cc", CC);
headers.Add("bcc", BCC);
if (Priority.Equals("High"))
{
headers.Add("X-Priority", "1 (Highest)");
headers.Add("X-MSMail-Priority", "High");
headers.Add("Importance", "High");
}
headers.Add("subject", Subject);
headers.Add("content-type", "text/html");
Status = SPUtility.SendEmail(spWeb, headers, Body);
}
}
});

WCF Self Host Via Https Fails

So I am pretty stuck here. I've always been able to host WCF apps with no problem over http. I can setup https WCF apps in IIS. But when I'm trying to use a self hosted https wcf app this has been nothing but a nightmare. I am running both the client and self hosted service on the same computer. Also, the service opens each time I run it with no errors. It's reported state is open. When I try to connect with the client (which is activating the service via channel factories) it crashes with the SSL/TLS error as described below. I've been at this for about 2 days now and can't get it to work :(
I have tried following several guides such as (but not limited to) the ones here: http://blogs.msdn.com/b/james_osbornes_blog/archive/2010/12/10/selfhosting-a-wcf-service-over-https.aspx as well as here: http://msdn.microsoft.com/en-us/library/ms733791.aspx. The first document I follow it to the letter and at the end when the author says "And that's it! now we can call the program and it will invoke the service" it doesn't. It gives me an error:
"Could not establish trust relationship for the SSL/TLS secure channel".
So I tried a slightly different approach upon coming on to the second article. I tried to use an existing certification already listed for my server (which is stored under personal certifcations). I copied the thumbprint and registered it with the port creating my own app id. That didn't work so I thought well lets try to force the client certificate thumbprint on both the service and the client by specifying the client credentials and looking it up via thumbprint like so:
factory.Credentials.ClientCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindByThumbprint,
"The actual thumbprint is here in my code");
I still get the same results. What am I missing? Here is the code for both the service and the client.
Client:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ServiceModel;
using HttpsSelfHost;
namespace ConsoleApp4
{
class Program
{
static void Main(string[] args)
{
string address = "https://localhost:8007/HelloWorldSvc";
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
try
{
ChannelFactory<IHelloWorldSvc> factory = new ChannelFactory<IHelloWorldSvc>(binding, address);
factory.Credentials.ClientCertificate.SetCertificate(System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine, System.Security.Cryptography.X509Certificates.StoreName.My,
System.Security.Cryptography.X509Certificates.X509FindType.FindByThumbprint, "f80e16f75e805b951e6099979f6dcea56bce3273");
IHelloWorldSvc client = factory.CreateChannel();
Console.WriteLine("Invoking service.");
string str = client.HelloWorld();
Console.WriteLine("Returned: {0}", str);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.WriteLine("Press enter to quit.");
Console.ReadLine();
}
}
}
Service:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ServiceModel;
namespace HttpsSelfHost
{
class Program
{
static void Main(string[] args)
{
string address = "https://localhost:8007/HelloWorldSvc";
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
using (ServiceHost host = new ServiceHost(typeof(HelloWorldSvc)))
{
host.AddServiceEndpoint(typeof(IHelloWorldSvc), binding, address);
host.Credentials.ClientCertificate.SetCertificate(System.Security.Cryptography.X509Certificates.StoreLocation.LocalMachine, System.Security.Cryptography.X509Certificates.StoreName.My,
System.Security.Cryptography.X509Certificates.X509FindType.FindByThumbprint, "f80e16f75e805b951e6099979f6dcea56bce3273");
host.Open();
Console.WriteLine("Host is: {0}. Press enter to close.", host.State);
Console.ReadLine();
host.Close();
}
}
}
}
It's likely that your client is rejecting the certificate during the negotiation process. I suspect that the certificate you bound on the port that the host is listening at is self-signed.
Here's something that you can use on the client in the testing environment and possibly production if you're okay with certificate pinning.
/// <summary>
/// Sets the Certificate Validation Policy for the Client
/// </summary>
public static void SetCertificatePolicy()
{
ServicePointManager.ServerCertificateValidationCallback
+= ValidateRemoteCertificate;
}
/// <summary>
/// Allows for validation of SSL conversations with the server.
/// </summary>
private static bool ValidateRemoteCertificate(object sender, X509Certificate cert,
X509Chain chain, SslPolicyErrors error)
{
if (cert.GetCertHashString() == "Your Certificate SHA1 HashString")
{
return true;
}
else
{
string text = "Failed to establish secure channel for SSL/TLS."
+ Environment.NewLine + Environment.NewLine +
"Connection with server has been disallowed.";
MessageBox.Show(text, #"SSL Validation Failure",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
return false;
}
}

How to send mails using SmtpClient and DefaultNetworkCredentials to a distribution list that only allows authenticated senders?

I'm trying to send automated emails from a C# console application from machines to clients all on the same domain via our internal Exchange 2007 server (using SMTP), but I'm hitting a snag with distribution lists that only allow authenticated senders. Basically the mails I'm sending are getting rejected by Exchange with:
#550 5.7.1 RESOLVER.RST.AuthRequired; authentication required ##rfc822;AuthTESTGroup#example.com
I'm using System.Net.Mail.SmtpClient and setting the Credentials property to System.Net.CredentialCache.DefaultNetworkCredentials, but somewhere along the line, the credentials of the account running this program (me, a valid domain user with a valid mailbox) are not getting passed down to Exchange correctly.
I'm using System.Net.CredentialCache.DefaultNetworkCredentials because I do not want to hard code a username or password (either in the code itself or in any sort of configuration file); I want the process to authenticate with our SMTP server using Windows authentication.
Here is a test program I've been using to reproduce the problem (domain names have been anonomized):
using System;
using System.Net.Mail;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
var smtpClient = new SmtpClient
{
Host = "MAIL",
Port = 25,
DeliveryMethod = SmtpDeliveryMethod.Network,
Credentials = System.Net.CredentialCache.DefaultNetworkCredentials
};
var mailMessage = new MailMessage
{
Body = "Testing",
From = new MailAddress(Environment.UserName + "#example.com"),
Subject = "Testing",
Priority = MailPriority.Normal
};
mailMessage.To.Add("AuthTESTGroup#example.com");
smtpClient.Send(mailMessage);
}
}
}
Whenever I run this as myself (again, I'm a valid user on the domain, with an existing mailbox on the Exchange server) I get an undeliverable bounce message from Exchange with the response:
#550 5.7.1 RESOLVER.RST.AuthRequired; authentication required ##rfc822;AuthTESTGroup#example.com
I talked to our Exchange server admin and he saw the following error from the Exchange server's event log:
Account For Which Logon Failed:
Security ID: NULL SID
Account Name:
Account Domain:
Failure Information:
Failure Reason: Unknown user name or bad password.
Status: 0xc000006d
Sub Status: 0xC0000064
Apparently that status code and sub status code translate to:
0xc000006d This is either due to a bad username or authentication information. Usually logged as status code with 0xc0000064 as substatus
0xC0000064 user name does not exist
So again, it's as if somewhere along the line, my Windows credentials are not getting passed down to the Exchange server even though I'm setting the SmtpClient.Credentials to System.Net.CredentialCache.DefaultNetworkCredentials
Any ideas?
Thanks in advance!
you need to pass username, password
here is a code snippet of how I would do it... keep in mind this is a code snippet you need to make the necessary changes to fit your Use Case
MailClient = new SmtpClient();
MailClient.Credentials = new System.Net.NetworkCredential(username, password);
below is another example but uses the server variable.. this maybe what you need to do try and let me know the server for example you can pass as your domain.com
example :
//SmtpClient client = new SmtpClient("smtp.contoso.com");//this would be server
//client.Credentials = CredentialCache.DefaultNetworkCredentials;
public static void CreateBccTestMessage(string server)
{
MailAddress from = new MailAddress("ben#contoso.com", "Ben Miller");
MailAddress to = new MailAddress("jane#contoso.com", "Jane Clayton");
MailMessage message = new MailMessage(from, to);
message.Subject = "Using the SmtpClient class.";
message.Body = #"Using this feature, you can send an e-mail message from an application very easily.";
MailAddress bcc = new MailAddress("manager1#contoso.com");
message.Bcc.Add(bcc);
SmtpClient client = new SmtpClient(server);
client.Credentials = CredentialCache.DefaultNetworkCredentials;
Console.WriteLine("Sending an e-mail message to {0} and {1}.",
to.DisplayName, message.Bcc.ToString());
try
{
client.Send(message);
}
catch (Exception ex)
{
Console.WriteLine("Exception caught in CreateBccTestMessage(): {0}",
ex.ToString());
}
}

Categories

Resources