How to set up sender informtion correctly of exchange address type - exchange-server

In some of the msg files the sender information got deleted accidentally. I want to restore the sender information back in msg file. I am using Redemption library to restore info.
The info is getting restored correctly. I have verified the info using MFCMAPI utility. Click to see sender info with Mapi
But when I open fixed msg with outlook, The sender's exchange canonical name is displayed with sender's display name in UI. e.g "John</O=Exchange/OU=ExchangeAdmin....>" in good msg it only displays "John".
Click to see UI display differences
I am using folowing code to restore sender info.
var PR_SENDER_ADDRTYPE_W = 0x0C1E001F;
var PR_SENDER_NAME_W = 0x0C1A001F;
var PR_SENDER_EMAIL_ADDRESS_W = 0x0C1F001F;
var PR_SENDER_SMTP_ADDRESS = 0x5D01001F;
Redemption.RDOSession oRdoSession = null;
RDOMail oRdoMail = null;
SafeMailItem sfItem = null;
oRdoSession = Redemption.RedemptionLoader.new_RDOSession(); // session = New Redemption.RDOSession
oRdoMail = oRdoSession.GetMessageFromMsgFile(sFilePath);
sfItem = Redemption.RedemptionLoader.new_SafeMailItem(); // CreateObject("redemption.safemailitem")
sfItem.Item = oRdoMail;
bool f_Changed = false;
var f_EntryID = oRdoSession.CreateOneOffEntryID(p_FromDisplayName, p_FromAddressType, p_FromEmailAddress, Type.Missing, Type.Missing);
var ID = oRdoSession.GetAddressEntryFromID(f_EntryID);
oRdoMail.Sender = ID;
oRdoMail.SentOnBehalfOf = ID;
//SetFieldValue is nothing but sfItem.Fields[PR_SENDER_ADDRTYPE_W] = p_FromAddressType
SetFieldValue(sfItem, PR_SENDER_ADDRTYPE_W, "PR_SENDER_ADDRTYPE_W", p_FromAddressType, ref f_Changed);
SetFieldValue(sfItem, PR_SENDER_NAME_W, "PR_SENDER_NAME_W", p_FromDisplayName, ref f_Changed);
SetFieldValue(sfItem, PR_SENDER_SMTP_ADDRESS, "PR_SENDER_SMTP_ADDRESS", p_FromSmtpAddress, ref f_Changed);
SetFieldValue(sfItem, PR_SENDER_EMAIL_ADDRESS_W, "PR_SENDER_EMAIL_ADDRESS_W", p_FromEmailAddress, ref f_Changed);
oRdoMail.Save();
Can you please let me know what am I missing.
For mor properties of sent info please check the screenshot.Click to see ScreenShot

Outlook actually displays the PR_SENT_REPRESENTING_xyz properties.
There is absolutely no reason to create an instance of the SafeMailItem - just use the RDOMail object returned by RDOSession.GetMessageFromMsgFile
What are the values of the p_FromAddressType and p_FromEmailAddress variables? If you know the SMTP address, simply pass it to CreateOneOffEntryID:
var f_EntryID = oRdoSession.CreateOneOffEntryID(p_FromDisplayName, "SMTP", p_FromSmtpAddress, Type.Missing, Type.Missing);

Related

How to set User Agent string in MSGraph .net SDK

I'm reading customer email accounts using the MSGraph SDK v4.27.0 in C#. It works fine but one customer insists on using allowlists for EWS access to email. That grants access to apps that supply a User Agent string but how do I include it in the MSGraph header using the SDK calls?
The code is taken from the MS example
var scopes = new[] { "User.Read","Mail.ReadWrite","Mail.ReadWrite.Shared" };
var options = new TokenCredentialOptions
{
AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
var userName = strAccount;
var password = strPWD ;
var userNamePasswordCredential = new UsernamePasswordCredential(
userName, password, tenantId, theClientId, options);
var graphClient = new GraphServiceClient(userNamePasswordCredential, scopes);
try
{
rootFolder = await graphClient.Me.MailFolders["msgfolderroot"]
.Request()
.GetAsync();
}..
Found the answer from the GitHubs docs eventually although it did take some experimentation finding out that the header option name is "User-Agent"
You create an options list and add in the user agent option
List<Option> theOptions = new List<Option>();
theOptions.Add(new HeaderOption("User-Agent", "MyUserAgentName"));
Then every .Request() call has to have the options as a parameter e.g.
rootFolder = await graphClient.Me.MailFolders["msgfolderroot"]
.Request(theOptions)
.GetAsync();

Not able to save a mailItem with protected attachment in outlook using c#

I'm trying to create a copy of a mailItem in my sent folder. Once I create it, I save the msg in the folder. It works for all mailItems , except when I try to save a mailItem with an attachment where I disallow the save attachment permission in outlook. Why does the mailItem.Save() not saving the mailItem only for this scenario?
In the code below, I'm using redemptions to create a copy in sent folder. msg.save() saves all mails but the one I mentioned above. Also I tried saving the mailItem before the creation, but it does not generate entryId.
static void CreateSentFolderMail(Redemption.SafeMailItem newSentMail, string nvdID, Outlook.MailItem mailItem, Redemption.SafeMailItem safeMailItem)
{
RDOFolder folder = Globals.ThisAddIn.session.GetDefaultFolder(rdoDefaultFolders.olFolderSentMail);
RDOMail msg = (RDOMail)folder.Items.Add(newSentMail);
RDOMail originalmsg = Globals.ThisAddIn.session.GetMessageFromID(mailItem.EntryID);
msg.Sent = true;
msg.SentOn = DateTime.Now;
msg.ReceivedTime =msg.CreationTime;
msg.Subject = safeMailItem.Item.Subject;
msg.To = safeMailItem.Item.To;
msg.BCC = safeMailItem.Item.BCC;
msg.Body = safeMailItem.Item.Body;
msg.Recipients = originalmsg.Recipients;
msg.Sender = Globals.ThisAddIn.session.CurrentUser;
msg.SentOnBehalfOf = Globals.ThisAddIn.session.CurrentUser;
msg.SetProps(NVDMailHeaderUtils.PS_INTERNET_HEADERS + NVDMailHeaderUtils.NVD_HEADER_ID, nvdID);
msg.Save();
}
I had used session.GetRDOObjectFromOutlookObject before calling this method to get a RDOAttachment object. But after using this: session.GetRDOObjectFromOutlookObject I was not able to the save the mailitem. Save was not getting executed and hence the EntryId was not getting generated. Due to this issue I was getting an error here : RDOMail originalmsg = Globals.ThisAddIn.session.GetMessageFromID(mailItem.EntryID); saying "invalid entry Id". I installed the new version of redemptions that solved this problem.

How do I create an HTML-formatted ICS message body using ical.net?

I need send reminders to users of a web application.
To do this I use iCal.Net from nuget packages. Following instructions about the usage I'm able to send an email with an attachment containing the ics file.
Is it possible to format the event description as html and make it working on both Outlook office client and Chrome calendar?
On these clients I see plain text representation with all the html tags. I tested also on Windows 10 calendar where the event description is correctly displayed as html. Do I have to set something more?
This is my calendar string generation
var now = DateTime.Now;
var later = scadenza.Value;
var e = new Event
{
DtStart = new CalDateTime(later),
DtEnd = new CalDateTime(later),
Description = mailText,
IsAllDay = true,
Created = new CalDateTime(DateTime.Now),
Summary = $"Reminder for XYZ",
};
var attendee = new Attendee
{
CommonName = "…..",
Rsvp = true,
Value = new Uri("mailto:" + ConfigurationManager.AppSettings["ReminderReceiver"])
};
e. Attendees = new List<IAttendee> { attendee };
var calendar = new Calendar();
calendar.Events.Add(e);
var serializer = new CalendarSerializer(new SerializationContext());
var icalString = serializer.SerializeToString(calendar);
HTML formatting isn't part of the icalendar spec, so it's up to applications to add support for this via the non-standard property fields, which are designated with an X- prefix. (Further reading on non-standard properties if you're interested.)
Google calendar
It doesn't look like Google calendar has any support for HTML-formatted events, so I think you're out of luck there.
Outlook
Outlook uses a number of these X- fields for various things; for HTML-formatted descriptions, it uses X-ALT-DESC and specifies FMTTYPE=text/html like this:
X-ALT-DESC;FMTTYPE=text/html:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//E
N">\n<HTML>\n<HEAD>\n<META NAME="Generator" CONTENT="MS Exchange Server ve
rsion rmj.rmm.rup.rpr">\n<TITLE></TITLE>\n</HEAD>\n<BODY>\n<!-- Converted
from text/rtf format -->\n\n<P DIR=LTR><SPAN LANG="en-us"><FONT FACE="Cali
bri">This is some</FONT></SPAN><SPAN LANG="en-us"><B> <FONT FACE="Calibri"
>HTML</FONT></B></SPAN><SPAN LANG="en-us"><FONT FACE="Calibri"></FONT></SP
AN><SPAN LANG="en-us"><U> <FONT FACE="Calibri">formatted</FONT></U></SPAN>
<SPAN LANG="en-us"><FONT FACE="Calibri"></FONT></SPAN><SPAN LANG="en-us"><
I> <FONT FACE="Calibri">text</FONT></I></SPAN><SPAN LANG="en-us"><FONT FAC
E="Calibri">.</FONT></SPAN><SPAN LANG="en-us"></SPAN></P>\n\n</BODY>\n</HT
ML>
You may be able to get away with much simpler HTML, you'll have to test to see what Outlook supports/allows. The HTML block above was generated using Outlook 2013. I have successfully used that block and run it through a serialization round-trip with ical.net, and Outlook opens it without any fuss.
ical.net
Unfortunately you can't quite do this in ical.net due a bug with CalendarProperty serialization, but the workaround is just one line.
const string formatted = //the text block from above starting with FMTTYPE=text/html:
var start = DateTime.Now;
var end = start.AddHours(1);
var #event = new Event
{
Start = new CalDateTime(start),
End = new CalDateTime(end),
Description = "This is a description",
};
var property = new CalendarProperty("X-ALT-DESC", formatted);
#event.AddProperty(property);
var calendar = new Calendar();
calendar.Events.Add(#event);
var serialized = new CalendarSerializer().SerializeToString(calendar);
//Workaround for the bug:
serialized = serialized.Replace("X-ALT-DESC:FMTTYPE=text/html", "X-ALT-DESC;FMTTYPE=text/html");
This will produce HTML-formatted Outlook calendar events.
(When I fix the bug, I'll update this answer to remove the string.Replace call.)

Storing emails in sent items of Outlook using add in

I am trying to develop an add in for Outlook in Visual Studio under .net framework 4.0. I used smtp protocol for sending an email from my Outlook addin. I am not able to find the sent mail in sent folder of Outlook.
How do I store sent mail in the sent folder of Outlook?
Till now I have written this code for sending mail.
public bool SendEMail(){
MailMessage mailNew = new MailMessage();
var smtp = new SmtpClient("SmtpServer")
{
EnableSsl = false,
DeliveryMethod = SmtpDeliveryMethod.Network
};
smtp.Port = 587;
smtp.DeliveryMethod = SmtpDeliveryMethod.Network;
smtp.UseDefaultCredentials = false;
System.Net.NetworkCredential credentials = new System.Net.NetworkCredential("UserName", "password");
smtp.EnableSsl = false;
smtp.Credentials = credentials;
MailAddress mailFrom = new MailAddress("clark#gmail.com");
mailNew.From = mailFrom;
mailNew.To.Add("someone#gmail.com");
mailNew.Subject = Subject;
mailNew.IsBodyHtml = Html;
mailNew.Body = Body;
smtp.Send(mailNew);
return true;
}
I want to add coding for storing the sent mail in sent folder of Outlook.
You will need to create a fake sent item. Note that messages in the Outlook Object Model are created in the unsent state, which cannot be modified.
The only exception is the post item. The following VB script creates a poat item in the Sent Item folder, resets the message class, reopens it as a regular MailItem (which is now in the sent state). Note that you cannot set the sender related properties using OOM alone and you cannot set the sent/received dates.
'create PostItem
set msg = Application.Session.GetDefaultFolder(olFolderSentMail).Items.Add("IPM.Post")
msg.MessageClass = "IPM.Note"
msg.Subject = "fake sent email"
msg.Body = "test"
msg.Save
vEntryId = msg.EntryID
set msg = Nothing 'release the mesage
'and reopen it as MailItem
set msg = Application.Session.GetItemFromID(vEntryId)
'make sure PR_ICON_INDEX is right
msg.PropertyAccessor.SetProperty "http://schemas.microsoft.com/mapi/proptag/0x10800003", -1
set vRecip = msg.Recipients.Add("fakeuser#domain.demo")
vRecip.Resolve
msg.Save
If using Redemption is an option, it lets you set the sent state before the first save (MAPI limitation) and allows to set the sender and date properties correctly:
set Session = CreateObject("Redemption.RDOSession")
Session.MAPIOBJECT = Application.Session.MAPIOBJECT
set msg = Session.GetDefaultFolder(olFolderSentMail).Items.Add("IPM.Note")
msg.Sent = true
msg.Subject = "fake sent email"
msg.Body = "test"
set vRecip = msg.Recipients.Add("fakeuser#domain.demo")
vRecip.Resolve
'dates
msg.SentOn = Now
msg.ReceivedTime = Now
'create fake sender
vSenderEntryID = Session.AddressBook.CreateOneOffEntryID("the sender", "SMTP", "me#domain.demo", true, true)
set vSender = Session.AddressBook.GetAddressEntryFromID(vSenderEntryID)
msg.Sender = vSender
msg.SentOnBehalfOf = vSender
msg.Save

Unable to set firefox bookmark description for in Add-On Kit API

I found the nsINavBookmarksService, however since Firefox 3, it does not seem to have any API methods for getting/setting the Bookmark description. (API doc)
I've seen other Add-Ons modify the description as a method of synchronized data storage (which is exactly what I'm trying to do). I'm guessing perhaps the description is a non-gecko standard, and that's why it is not directly supported, but then there must be a completely different interface for manipulating Bookmarks that I haven't discovered.
Can anyone help with this newbie problem?
Starting with Firefox 3 the bookmarks have been merged into the Places database containing all of your browsing history. So to get the bookmarks you do a history query, like this (first line is specific to the Add-on SDK which you appear to be using):
var {Cc, Ci} = require("chrome");
var historyService = Cc["#mozilla.org/browser/nav-history-service;1"]
.getService(Ci.nsINavHistoryService);
var options = historyService.getNewQueryOptions();
var query = historyService.getNewQuery();
query.onlyBookmarked = true;
var result = historyService.executeQuery(query, options);
result.root.containerOpen = true;
for (var i = 0; i < result.root.childCount; i++)
{
var node = result.root.getChild(i);
console.log(node.title);
}
That's mostly identical to the code example here. Your problem is of course that nsINavHistoryResultNode has no way of storing data like a description. You can set annotations however, see Using the Places annotation service. So if you already have a node variable for your bookmark:
var annotationName = "my.extension.example.com/bookmarkDescription";
var ioService = Cc["#mozilla.org/network/io-service;1"]
.getService(Ci.nsIIOService);
var uri = ioService.newURI(node.uri, null, null);
var annotationService = Cc["#mozilla.org/browser/annotation-service;1"]
.getService(Ci.nsIAnnotationService);
annotationService.setPageAnnotation(uri, annotationName,
"Some description", 0, Ci.nsIAnnotationService.EXPIRE_NEVER);
For reference: nsIAnnotationService.setPageAnnotation()

Resources