With reference to my previous question, I already wrote my program and it is working awesome when I am using VS2008 for run it.
I have two more questions:
1. I want to check with you guys when I run my program all the mail are appearing in VS output as xml file, but I never used to print them in output. is it usual for all or I need to add something to remove it. I feel it takes long time from my PC to show mails in output.
2. my second question is that when I want to use only exe file stand alone(run program via exe file not with VS ) I am receiving below error and program is hanging & close.
"MailReader has encountered a problem and needs to close. We are
sorry for the inconvenience."
As I mentioned above this program is working fine in VS.
I copy part of my code that read mails and split them for your reference.
public void ReadMail()
{
ServicePointManager.ServerCertificateValidationCallback += delegate(object sender,
X509Certificate certificate,
X509Chain chain,
SslPolicyErrors sslPolicyErrors) { return true; };
try
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.TraceEnabled = true;
service.Credentials = new WebCredentials(_username, _password); //Modify this
service.Url = new Uri(_exchange); //Modify this
service = new ExchangeService(ExchangeVersion.Exchange2007_SP1);
service.Url = new Uri(_exchange);
service.TraceEnabled = true;
service.Credentials = new WebCredentials(_username, _password); //Modify this
service.Url = new Uri(_exchange);
//SearchFilter to get unreaded messages only.
SearchFilter sf = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter.IsEqualTo(EmailMessageSchema.IsRead, false));
ItemView itemview = new ItemView(Int16.MaxValue);
//DateTime searchdate = new DateTime(2012, 7, 6); //Year, month, day
SearchFilter greaterthanfilter = new SearchFilter.IsGreaterThan(ItemSchema.DateTimeSent, Convert.ToDateTime(startDate));
SearchFilter lessthanfilter = new SearchFilter.IsLessThan(ItemSchema.DateTimeSent,Convert.ToDateTime(finishDate));
SearchFilter[] f = { greaterthanfilter, lessthanfilter };
SearchFilter filter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, f);
//Folder folder = Folder.Bind(this.m_Service, WellKnownFolderName.MsgFolderRoot); //Or the folder you want to search in
//FindItemsResults<Item> results = folder.FindItems(filter, new ItemView(1000));
FindItemsResults<Item> findResults = service.FindItems(WellKnownFolderName.SentItems,filter, itemview);
Action action = () => fr.setText(findResults.Items.Count + "mails need to analysis from "+startDate +" to "+ finishDate);
fr.Invoke(action, null);
action = () => fr.setMaximumProgressBar(findResults.Items.Count);
fr.Invoke(action, null);
dmd = new List<DailyMailDetails>();
foreach (Item item in findResults.Items)
{
string messageDate = "Error in Date";
string messageSubj = "Error in Subject";
int index = 0;
try
{
PropertySet propertySet = new PropertySet(BasePropertySet.FirstClassProperties, ItemSchema.DateTimeSent, ItemSchema.Body, ItemSchema.Subject);
propertySet.RequestedBodyType = BodyType.Text;
EmailMessage message = EmailMessage.Bind(service, item.Id, propertySet);
string temp = startSign.ToUpper();
int start = message.Body.Text.ToUpper().IndexOf(temp) + temp.Length;
int end = message.Body.Text.ToUpper().IndexOf(finishSign.ToUpper());
int len = end - start;
string text = message.Body.Text.Substring(start, len);
index = findDmdIndex(message.DateTimeSent.ToShortDateString().ToString());
if (index == -1)
{
dmd.Add(new DailyMailDetails(message.DateTimeSent.ToShortDateString().ToString(), (List<PeopleSigniture>)Extensions.Clone<PeopleSigniture>(OrginallistPeopleSign)));
index = dmd.Count - 1;
}
bool signExist = false;
for (int i = 0; i < listPeopleSign.Count; i++)
if (text.ToUpper().Contains(dmd[index].peopleSign[i].Signiture.ToUpper()))
{
dmd[index].peopleSign[i].addResponse(message.DateTimeSent.ToString(), message.Subject.ToString());
signExist = true;
break;
}
messageDate = message.DateTimeSent.ToString();
messageSubj = message.Subject.ToString();
if (!signExist)
dmd[index].peopleSign[dmd[index].peopleSign.Count - 2].addResponse(message.DateTimeSent.ToString(), message.Subject.ToString());
}
catch (Exception ex)
{
dmd[index].peopleSign[dmd[index].peopleSign.Count - 1].addResponse(messageDate, messageSubj);
}
action = () => fr.increasePrograss();
fr.Invoke(action, null);
}
}
catch (Exception ex)
{
MessageBox.Show("Class: Mail Function:ReadMail" + ex.Message);
}
Action action2 = () => fr.setText(ToString(true),dmd);
fr.Invoke(action2, null);
}
For issue #1 - you are viewing the XML output likely because you have EWS tracing enabled. You need to set ExchangeService.TraceEnabled to false or comment it out entirely. (You also have many duplicate lines of code you need to cleanup.)
service.TraceEnabled = false;
For issue #2 - you need to determine the actual .NET exception. Without this - we cannot help you further. It could be crashing for countless reasons. Please provide a stack trace.
Related
I have developed an engine to automatically process the emails sent to a particular mailbox using EWS (Exchange Web Services) Push Subscription. Everything is working fine except, I need to set the follow-up flag text with some custom message like we do in outlook (screen-shots below):
Custom text:
Sample email after setting the flag text:
I am using below code to do that, however the text is not displayed on email, only dates are reflecting with below code:
public bool MoveToFolder(EmailMessage mail, string folderName, bool MarkForFollowUp, string FollowUpText)
{
try
{
var folderView = new FolderView(100);
if (MarkForFollowUp)
{
try
{
ExtendedPropertyDefinition followUpTextFlag = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, "ChangeDetails", MapiPropertyType.String);
Flag flag = new Flag();
flag.FlagStatus = ItemFlagStatus.Flagged;
flag.StartDate = DateTime.Now;
flag.DueDate = DateTime.Now.AddHours(1);
mail.Flag = flag;
workLog.WriteVerbose($"Setting flag with followup-text: {FollowUpText}", "Notify.cs > MoveToFolder()");
mail.SetExtendedProperty(followUpTextFlag, FollowUpText);
mail.Update(ConflictResolutionMode.AutoResolve);
workLog.WriteVerbose($"Message follow-up flag set successfully.", "Notify.cs > MoveToFolder()");
}
catch (Exception ex)
{
// Ignore error while settings the flag
workLog.WriteVerbose($"Error occurred while setting the follow-up flag. Reason: {ex.Message}", "Notify.cs > MoveToFolder()");
}
}
folderView.PropertySet = new PropertySet(BasePropertySet.IdOnly);
folderView.PropertySet.Add(FolderSchema.DisplayName);
folderView.Traversal = FolderTraversal.Deep;
FindFoldersResults findFolderResults = _service.FindFolders(WellKnownFolderName.Root, folderView);
if (findFolderResults == default(FindFoldersResults))
{
return false;
}
try
{
FolderId folderId = findFolderResults.Cast<Folder>().FirstOrDefault(Folder => Folder.DisplayName == folderName).Id;
mail.Move(folderId);
return true;
}
catch
{
return false;
}
}
catch (Exception)
{
return false;
}
}
You need to set the PidLidFlagRequest extended property https://learn.microsoft.com/en-us/office/client-developer/outlook/mapi/pidlidflagrequest-canonical-property with the text you want to show eg
ExtendedPropertyDefinition followUpTextFlag = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, "ChangeDetails", MapiPropertyType.String);
ExtendedPropertyDefinition PidLidFlagRequest = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Common, 0x8530, MapiPropertyType.String);
ExtendedPropertyDefinition PidLidFlagString = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.Common, 0x85C0, MapiPropertyType.Integer);
Flag flag = new Flag();
flag.FlagStatus = ItemFlagStatus.Flagged;
flag.StartDate = DateTime.Now;
flag.DueDate = DateTime.Now.AddHours(1);
mail.Flag = flag;
mail.SetExtendedProperty(PidLidFlagRequest, "PidFlag Blah Blah");
mail.SetExtendedProperty(PidLidFlagString, 0);
mail.SetExtendedProperty(followUpTextFlag, "Blah Balh");
mail.Update(ConflictResolutionMode.AutoResolve);
I am trying to find the unique id of a folder in Outlook.
For some reason I keep getting an error with the AutoDiscoverUrl method, but I have no idea why. I have tried all the possible solutions on StackOverflow.
I am trying to run it in a commandline program using C#, and have commented/documented the code. I have used others' example on how to do this, but it doesn't work.
static void Main(string[] args)
{
// Set server binding
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
service.UseDefaultCredentials = true;
// Set Credentials
service.Credentials = new WebCredentials("xxxx", "xxxxx", "xxxx");
service.UseDefaultCredentials = true;
service.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
// Set the URL
service.AutodiscoverUrl("xxxx", Callback);
// Error Tracing
service.TraceEnabled = true;
// Redirect callback
// Set View
FolderView view = new FolderView(100);
view.PropertySet = new PropertySet(BasePropertySet.IdOnly);
view.PropertySet.Add(FolderSchema.DisplayName);
view.Traversal = FolderTraversal.Deep;
FindFoldersResults findFolderResults = service.FindFolders(WellKnownFolderName.Root, view);
// Find specific folder
foreach (Folder f in findFolderResults)
{
// Show FolderId of the folder "test"
if (f.DisplayName == "test")
{
Console.WriteLine(f.Id);
}
}
}
private static bool Callback(string redirectionUrl)
{
bool result = false;
var redirectionUri = new Uri(redirectionUrl);
if (redirectionUri.Scheme == "https")
{
result = true;
}
return result;
}
You could find the unique id of the folder using the below code:
ExchangeService Service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
Service.UseDefaultCredentials = false;
Service.Credentials = new WebCredentials("yourUserID", "yourPassword");
Mailbox ProdSupportMailbox = new Mailbox("ProdSupport#company.com");
Service.AutodiscoverUrl("ProdSupport#company.com");
FolderView view = new FolderView(100);
view.PropertySet = new PropertySet(BasePropertySet.IdOnly);
view.PropertySet.Add(FolderSchema.DisplayName);
view.Traversal = FolderTraversal.Deep;
FindFoldersResults findFolderResults = server.FindFolders(WellKnownFolderName.Root, view);
// find specific folder
foreach(Folder f in findFolderResults)
{
// show folderId of the folder "Test"
if (f.DisplayName == "Test")
{
Console.WriteLine(f.Id);
}
}
For more information, please refer to these links:
Exchange Web Service FolderId for a not well known folder name
Microsoft Exchange Web Services reading my local Outlook folders INSTEAD of another address
My code below is performing very poorly. I used the .Net StopWatch class to find out what piece of code was causing the slowness.
This line seems to be the issue:
message.SendAndSaveCopy();
E.G batch of 20 emails: 1st email takes around 2 seconds to send and this time gradually increases until the 20th email, which takes up-to 18 seconds.
public int SendBulkMarketing(bool CheckDelivery)
{
int iCounter = 0;
DataTable dt = null;
try
{
DeliveryReportDAL myDeliveryReportDAL = new DeliveryReportDAL();
dt = myDeliveryReportDAL.GetListMessageToSend('E');
if (dt == null) return iCounter;
iCounter = dt.Rows.Count;
}
catch (Exception ex)
{
new Util().LogError(ex, "SMTP:: SendBulkMarketing 1st catch");
return 0;
}
if (iCounter > 0)
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013_SP1);
service.Credentials = new WebCredentials(Account_UserName, Account_Password, Account_Domain);
service.Url = new Uri(Service_URL);
for (int I = 0; I < iCounter; ++I)
{
try
{
string myGUID = "{" + dt.Rows[I]["GUID"].ToString() + "}";
if (IsValidEmailAddress(dt.Rows[I]["OwnerEmail"].ToString()) == false)
{
DeliveryReportDAL myReport = new DeliveryReportDAL();
myReport.SaveSentStatus(myGUID, 'G', 3);
continue;
}
EmailMessage message = new EmailMessage(service);
message.Subject = dt.Rows[I]["TemplateSubject"].ToString();
message.Body = dt.Rows[I]["TemplateText"].ToString().Replace("\0", " ");
message.ToRecipients.Add(dt.Rows[I]["OwnerEmail"].ToString());
message.IsDeliveryReceiptRequested = true;
Guid myPropertySetId = new Guid(myGUID);
ExtendedPropertyDefinition myExtendedPropertyDefinition = new ExtendedPropertyDefinition(myPropertySetId, "blablabla", MapiPropertyType.String);
ServicePointManager.ServerCertificateValidationCallback =
delegate(object sender1,
System.Security.Cryptography.X509Certificates.X509Certificate certificate,
System.Security.Cryptography.X509Certificates.X509Chain chain,
System.Net.Security.SslPolicyErrors sslPolicyErrors)
{ return true; };
message.SendAndSaveCopy();
DeliveryReportDAL myReport1 = new DeliveryReportDAL();
myReport1.SaveSentStatus(dt.Rows[I]["GUID"].ToString(), 'G', 1);
}
catch (Exception ex)
{
new Util().LogError(ex, "SMTP:: SendBulkMarketing 2nd catch");
}
}
}
return iCounter;
}
I would greatly appreciate any help in improving the performance of my code.
This performance issue is now resolved.
It was a fundamental coding problem. The issue was caused by a separate method call which was being called (not shown in the code snippet provided) inside the for loop. It contains performance heavy functionality, but it did not need to be called inside the for loop.
Moving this performance heavy method call outside of the for loop resolved the issue.
I am using ASP.Net MVC.
using (ExchangeServiceBinding exchangeServer = new ExchangeServiceBinding())
{
ICredentials creds = new NetworkCredential("username", "password");
exchangeServer.Credentials = creds;
exchangeServer.Url = "https://myexchangeserver.com/EWS/Exchange.asmx";
FindItemType findItemRequest = new FindItemType();
findItemRequest.Traversal = ItemQueryTraversalType.Shallow;
// define which item properties are returned in the response
ItemResponseShapeType itemProperties = new ItemResponseShapeType();
itemProperties.BaseShape = DefaultShapeNamesType.AllProperties;
findItemRequest.ItemShape = itemProperties;
// identify which folder to search
DistinguishedFolderIdType[] folderIDArray = new DistinguishedFolderIdType[1];
folderIDArray[0] = new DistinguishedFolderIdType();
folderIDArray[0].Id = DistinguishedFolderIdNameType.inbox;
// add folders to request
findItemRequest.ParentFolderIds = folderIDArray;
// find the messages
FindItemResponseType findItemResponse = exchangeServer.FindItem(findItemRequest);
// read returned
FindItemResponseMessageType folder = (FindItemResponseMessageType)findItemResponse.ResponseMessages.Items[0];
ArrayOfRealItemsType folderContents = new ArrayOfRealItemsType();
folderContents = (ArrayOfRealItemsType)folder.RootFolder.Item;
ItemType[] items = folderContents.Items;
// if no messages were found, then return null -- we're done
if (items == null || items.Count() <= 0)
{ return null; }
// FindItem never gets "all" the properties, so now that we've found them all, we need to get them all.
BaseItemIdType[] itemIds = new BaseItemIdType[items.Count()];
for (int i = 0; i < items.Count(); i++)
{
itemIds[i] = items[i].ItemId;
}
GetItemType getItemType = new GetItemType();
getItemType.ItemIds = itemIds;
getItemType.ItemShape = new ItemResponseShapeType();
getItemType.ItemShape.BaseShape = DefaultShapeNamesType.AllProperties;
getItemType.ItemShape.BodyType = BodyTypeResponseType.HTML;
getItemType.ItemShape.BodyTypeSpecified = true;
GetItemResponseType getItemResponse = exchangeServer.GetItem(getItemType);
ItemType[] messages = new ItemType[getItemResponse.ResponseMessages.Items.Count()];
List<MailRecipientModel> model = new List<MailRecipientModel>();
for (int j = 0; j < messages.Count(); j++)
{
messages[j] = ((ItemInfoResponseMessageType)getItemResponse.ResponseMessages.Items[j]).Items.Items[0];
MailRecipientModel model1 = new MailRecipientModel();
model1.Subject = messages[j].Subject;
model1.FromAddress = messages[j].Sender.Item.EmailAddress;
model1.DisplayName = messages[j].Sender.Item.Name;
model1.Date = messages[j].DateTimeReceived.Date.ToString();
model1.MailBody = messages[j].Body.Value;
model1.MsgId = messages[j].ItemId.Id;
if (messages[j].Attachments != null) {
//
}
model.Add(model1);
}
return model;
}
This my code I wanna download attachment file and if attachment file is image so its display in browser.
I am using Microsoft ActiveSync Exchange Server.
If you know how to do so please help me.
public List<FileAttachment> getAttachmentFromExchangeAccount( ExchangeAccounts exchangeAccount, String attachmentId, String itemId) {
ExchangeService service = obtainExchangeService(exchangeAccount);
List<FileAttachment> fileAttachmentsEWS = new ArrayList<>();
try {
EmailMessage message = EmailMessage.bind(service, new ItemId(attachmentId), new PropertySet(ItemSchema.Attachments));
message.load();
for (Attachment attachment : message.getAttachments()) {
attachment.load();
if (attachment.getId().equals(itemId)) {
FileAttachment fileAttachment = (FileAttachment) attachment;
fileAttachment.load();
fileAttachmentsEWS.add(fileAttachment);
}
}
} catch (ServiceLocalException e) {
LOG.debug("OUT NOK loadAttachmentFile ServiceLocalException");
LOG.debug(e.getMessage());
} catch (Exception e) {
LOG.debug("OUT NOK loadAttachmentFile Exception");
LOG.debug(e.getMessage());
}
return fileAttachmentsEWS;
}
You should be using the GetAttachment operation https://msdn.microsoft.com/en-us/library/office/aa494316(v=exchg.150).aspx . There is a Proxy code sample https://blogs.msdn.microsoft.com/vikas/2007/10/15/howto-ews-use-getattachment-to-download-attachments-off-mailappointment/
I searched a lot how to read an email from gmail and then mark it as unread (unseen), now that I found I wanted to share with everyone.
using library http://mailsystem.codeplex.com/
Source: http://mailsystem.codeplex.com/discussions/269058
add reference: activeup.net.common, activeup.net.imap4, activeup.net.mail
code:
Imap4Client imap = new Imap4Client();
imap.ConnectSsl("imap.gmail.com", 993);
imap.Login("aaaaa#gmail.com", "xxxxxxx");
imap.Command("capability");
Mailbox inbox = imap.SelectMailbox("inbox");
int[] ids = inbox.Search("UNSEEN");
if (ids.Length > 0)
{
ActiveUp.Net.Mail.Message msg_first = inbox.Fetch.MessageObject(ids[0]);
//ignore this gmail_data stuff // undefined in this scope // checking to make sure it's a "new" unread msg
//if (gmail_data != msg_first.Date.ToString())
//{
// gmail_data = msg_first.Date.ToString();
XElement xmail = new XElement("gmail",
new XAttribute("count", ids.Length.ToString()),
new XAttribute("modified", msg_first.Date.ToString())
);
string name = "", address = "", from = "";
Regex reg_name = new Regex("\"[^\"]+");
Regex reg_address = new Regex("<[^>]+");
ActiveUp.Net.Mail.Message msg = null;
for (var i = 0; i < ids.Length; i++)
{
msg = inbox.Fetch.MessageObject(ids[i]);
from = msg.HeaderFields["from"];
name = reg_name.Match(from).Value.Replace("\"", "");
address = reg_address.Match(from).Value.Replace("<", "");
xmail.Add(new XElement("entry",
new XAttribute("id", msg.MessageId),
new XAttribute("modified", msg.Date.ToString()),
new XAttribute("name", name),
new XAttribute("address", address),
new XElement("subject", msg.Subject),
new XElement("body-text", msg.BodyText.TextStripped),
new XElement("body-html", msg.BodyHtml.Text)
));
//mark as unread
var flags = new FlagCollection();
flags.Add("Seen");
inbox.RemoveFlags(ids[i], flags);
}
File.WriteAllText("gmail.xml", xmail.ToString());
}
}
When you get all e-mail´s from server, the API automaticaly marks all e-mail´s as "seen/readed", and i think there´s no way to use the "search method" filtering by messageId, so you must get all e-mail to mark one (seen) e-mail as unread.
You should get allways just the "unread massages" and add on a list the messageId of the e-mail´s that you want to mark as "unread", then you must pass the list to the method bellow, that will mark as unread all messages of the list.
Possible code:
public void MarkAsUnread(List<string> messageIdList)
{
Mailbox inbox = Client.SelectMailbox("inbox");
int[] ids = inbox.Search("ALL");
int ListCount = messageIdList.Count;
int MarkedAsUnread = 0;
if (ids.Length > 0)
{
ActiveUp.Net.Mail.Message msg = null;
for (var i = 0; i < ids.Length; i++)
{
msg = inbox.Fetch.MessageObject(ids[i]);
// if messageId is on the list, mark as unread.
if (String.Join(",", messageIdList).Contains(msg.MessageId))
{
var flags = new FlagCollection { "Seen" };
inbox.RemoveFlagsSilent(i+1, flags);
MarkedAsUnread = MarkedAsUnread + 1;
}
// optimization
if (MarkedAsUnread == ListCount)
{
break;
}
}
}
}
*If you really don´t want to get all, maybe you could filter by date using some code like that:
var box = imap.SelectMailbox("inbox");
var ids = box.Search("OR (CC #cc.lieser-online.de) (HEADER Envelope-To #cc.lieser-online.de)");