I want to do the following (pseudo-code) with outlook API or outlook redemption
var sourceMessage = Folder.Item[count];
//Check if source is encryted
if(sourceMessage is EncryptedMessageType)
{
//Created a new message on target destination, and copy encrypted bytes
var targetItem = TargetFolder.Items.Add(EncrytedMessageType)
targetItem.Body = sourceMessage.Body;
targetItem.EncryptionType = sourceMessage.EncryptionType;
targetItem.Save();
}
Is this possible?
I looked up the RDOEncryptedMessage object but all the proprieties looks read only.
Why not copy the source message (sourceMessage)?
sourceMessage .CopyTo(TargetFolder) should do the job.
Related
I have just started learning how to program add-ins for Outlook using Visual Studio. I am having a hard time finding resources to read up on VSTO. How can I cannot modify the default fonts for "New mail messages" and "Replying or forwarding messages" under Personal Stationery in Outlook?
Revised my post to include the solution:
I am using code from this link (https://pcloadletter.co.uk/2010/05/19/outlook-default-font-and-signature/) and converted to c#. For those that are trying to do the same, here is how I did it.
private void SetFont()
{
RegistryKey key = Registry.CurrentUser.OpenSubKey(#"SOFTWARE\Microsoft\Office\16.0\Common\MailSettings", true);
// set the font in Outlook and then export it from the registry. Use that value for our code.
string ComposeFontSimple = #"3c,00,00,00,1f,00,00,f8,00,00,00,00,c8,00,00,00,00,00,
00,00,ff,ff,00,dd,00,22,41,72,69,61,6c,00,00,00,00,00,00,00,00,00,00,00,00,
00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00";
byte[] arrComposeFontSimpleBin = ArrayHexToDec(ComposeFontSimple.Split(','));
key.SetValue("ComposeFontSimple", arrComposeFontSimpleBin, RegistryValueKind.Binary);
}
public static byte[] ArrayHexToDec(string[] arrHex)
{
byte[] arrDec = new byte[arrHex.GetUpperBound(0)];
for (int i = 0; i < arrHex.GetUpperBound(0); i++)
{
if (arrHex[i] == "00")
{
arrDec[i] = 0;
}
else
{
arrDec[i] = byte.Parse(arrHex[i], System.Globalization.NumberStyles.HexNumber);
}
}
return arrDec;
}
The settings are stored at HKCU\Software\Microsoft\Office\%s.0\Common\MailSettings.
The value you want is ReplyFontSimple - font size starts at offset 12, and name start at offset 0x1A (0x0 terminated string).
Outlook keeps its setting in the windows registry. Try using the Process Monitor for tracking where exactly Outlook saves its settings.
If we speak about making changes to Outlook mail items at runtime, the message body can be modified using three different ways:
Body.
HTMLBody.
The Word editor. The WordEditor property of the Inspector class returns an instance of the Word Document which represents the message body.
See Chapter 17: Working with Item Bodies for more information.
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.
I am trying to import Attachments/Annotations to CRM Dynamics, I am doing this using the SDK.
I am not using the data import wizard.
I am not individually creating Annotation entities, instead I am using Data Import Feature programmatically.
I mostly leveraged the DataImport sample from the SDK sample code (SDK\SampleCode\CS\DataManagement\DataImport).
Import import = new Import()
{
ModeCode = new OptionSetValue((int)ImportModeCode.Create),
Name = "Data Import"
};
Guid importId = _serviceProxy.Create(import);
_serviceProxy.Create(
new ColumnMapping()
{
ImportMapId = new EntityReference(ImportMap.EntityLogicalName, importMapId),
ProcessCode = new OptionSetValue((int)ColumnMappingProcessCode.Process),
SourceEntityName = sourceEntityName,
SourceAttributeName = sourceAttributeName,
TargetEntityName = targetEntityName,
TargetAttributeName = targetAttributeName
});
I am getting an error "The reference to the attachment could not be found".
The documentation says the crm async service will find the physical file on disk and upload it, my question is where does the async service look for attachment files?
I tried to map documentbody field to the full path of the attachment on the desk, but that still didn't work.
The answer below was provided before the question edits clarifying the use of the import wizard instead of the SDK. The answer below is specific to using the SDK.
When you are attaching files to an Annotation (Note) record in CRM via the SDK, you do use the documentbody attribute (along with mimetype), but you have to first convert it base64.
Something like this:
var myFile = #"C:\Path\To\My\File.pdf";
// Do checks to make sure file exists...
// Convert to Base64.
var base64Data = Convert.ToBase64String(System.IO.File.ReadAllBytes(myFile));
var newNote = new Entity("annotation");
// Set subject, regarding object, etc.
// Add the data required for a file attachment.
newNote.Attributes.Add("documentbody", base64Data);
newNote.Attributes.Add("mimetype", "text/plain"); // This mime type seems to work for all file types.
orgService.Create(newNote);
I found the solution in an obscure blog post, I think the documentation is misleading or unclear, the way this whole thing works, makes having the files available on the server disk for the async to process, odd.
To follow the same principle, all contents should be sent like the csv file itself while being linked to the same import.
To solve this we need create individual special Internal ImportFile for each physical attachment, and link it to the import that has the attachments record details.
As you see below with linking the attachments ImportFile using the ImportId and then setting the two properties (ProcessCode and FileTypeCode), it all worked in the end.
Suffice to say using this method is much more efficient and quicker than individually creating Annotation records.
foreach (var line in File.ReadLines(csvFilesPath + "Attachment.csv").Skip(1))
{
var fileName = line.Split(',')[0].Replace("\"", null);
using (FileStream stream = File.OpenRead(attachmentsPath + fileName))
{
byte[] byteData = new byte[stream.Length];
stream.Read(byteData, 0, byteData.Length);
stream.Close();
string encodedAttachmentData = System.Convert.ToBase64String(byteData);
ImportFile importFileAttachment = new ImportFile()
{
Content = encodedAttachmentData,
Name = fileName,
ImportMapId = new EntityReference(ImportMap.EntityLogicalName, importMapId),
UseSystemMap = true,
ImportId = new EntityReference(Import.EntityLogicalName, importId),
ProcessCode = new OptionSetValue((int)ImportFileProcessCode.Internal),
FileTypeCode = new OptionSetValue((int)ImportFileFileTypeCode.Attachment),
RecordsOwnerId = currentUserRef
};
_serviceProxy.Create(importFileAttachment);
}
idx++;
}
I'm writing an Outlook 2010 add-in with VSTO, one part of which will automatically add the correct email signature to a new AppointmentItem. The issue I've come across is how to determine which signature is the correct one. For example, I have 2 email signatures set up in Outlook, which have rules on use based on which address my email is coming from. How can I access these rules?
My issue is not with finding the signature files, but in applying the correct rules based on the user's settings. Any ideas?
You can access the rules by using the code below. You can loop through them and get the rule type and actions
app is the current instance of the Outlook.Application
Outlook.Rules rules= app.Session.DefaultStore.GetRules();
foreach (Outlook.Rule r in rules)
{
}
I ended up solving this by creating a dictionary object with the key being the email address and the value as the filepath:
private Dictionary<string, string> signatureDictionary()
{
string sigDataDir = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\Microsoft\Signatures";
Dictionary<string, string> returnValue = new Dictionary<string,string>();
Microsoft.Win32.RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(#"Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\Outlook\9375CFF0413111d3B88A00104B2A6676", false);
string[] str = key.GetSubKeyNames();
foreach (string s in str)
{
Microsoft.Win32.RegistryKey subKey = key.OpenSubKey(s, false);
if (subKey.GetValue("New Signature") != null)
{
returnValue.Add(System.Text.Encoding.Unicode.GetString(subKey.GetValue("Account Name") as
Byte[],0,(subKey.GetValue("Account Name") as Byte[]).Length - 2)
, Path.Combine(sigDataDir,System.Text.Encoding.Unicode.GetString(
subKey.GetValue("New Signature") as Byte[], 0, (subKey.GetValue("New Signature") as
Byte[]).Length - 2) + #".rtf"));
}
}
key.Close();
return returnValue;
}
This answer to a similar question initially pointed me in the right direction, and figuring out that the "New Signature" key is only populated when a signature has been set for that account. Undoubtedly there will be situations where this doesn't work, but it sorts it out for my current issue. Since I use the WordEditor when I'm editing emails in VSTO I use the RTF files in this function, but there are also .HTM and .TXT files in the same directory so you can use those if you prefer.
I have an inbox set up in exchange, hello#mycompany.com
Additionally, there is an alias for this, news#mycompany.com, so all emails to the news address end up in the hello inbox.
Ideally, I want to be able to tell which alias an email has been sent to, using EWS.
When I send an email to news#mycompany.com, and examine the Internet headers of the message using Microsoft Outlook, the To: header reads To: Hello <news#mycompany.com> which is exactly what I want to see.
However, using EWS, when I look at the ToRecipients property of the message, the reported email address is always that of the primary SMTP address. Also the InternetMessageHeaders property of the Webservices.Data.Item does not contain the To: property. I also can't seem to see the correct address using EWSEditor to examine all the properties of the message.
The answer to this forum post seems to suggest that,
...The Information about the actual email address a message is sent to is stored in the recipients collection which you can't access (outside of exportmessage) in EWS...
How would I go about doing this programatically so I can find the correct To: address?
This works for me:
private static string GetToAddress()
{
ExchangeService exService = new ExchangeService();
exService.Credentials = new NetworkCredential("username", "password", "domain");
exService.Url = new Uri("https://youraddress/EWS/Exchange.asmx");
ExtendedPropertyDefinition PR_TRANSPORT_MESSAGE_HEADERS = new ExtendedPropertyDefinition(0x007D,MapiPropertyType.String);
PropertySet psPropSet = new PropertySet(BasePropertySet.FirstClassProperties)
{PR_TRANSPORT_MESSAGE_HEADERS, ItemSchema.MimeContent};
FindItemsResults<Item> fiResults = exService.FindItems(WellKnownFolderName.Inbox, new ItemView(1));
foreach (Item itItem in fiResults.Items)
{
itItem.Load(psPropSet);
Object valHeaders;
if (itItem.TryGetProperty(PR_TRANSPORT_MESSAGE_HEADERS, out valHeaders))
{
Regex regex = new Regex(#"To:.*<(.+)>");
Match match = regex.Match(valHeaders.ToString());
if (match.Groups.Count == 2)
return match.Groups[1].Value;
}
return ToAddress;
}
return "Cannot find ToAddress";
}
The code is from:
http://social.technet.microsoft.com/Forums/en-au/exchangesvrdevelopment/thread/1e5bbde0-218e-466e-afcc-cb60bc2ba692