Read sender's email address from MS Outlook mail - c#

I am using below code to read incoming mails from MS Outlook 2010 -
public static void outLookApp_NewMailEx(string EntryIDCollection)
{
NameSpace _nameSpace;
ApplicationClass _app;
_app = new ApplicationClass();
_nameSpace = _app.GetNamespace("MAPI");
object o = _nameSpace.GetItemFromID(EntryIDCollection);
MailItem Item = (MailItem)o;
string HTMLbpdyTest = Item.HTMLBody;
string CreationTime = Convert.ToString(Item.CreationTime);
string strEmailSenderEmailId = Convert.ToString(Item.SenderEmailAddress);
string strEmailSenderName = Item.SenderName;
string Subject = Item.Subject;
}
How can I get sender's mail id. I tried Item.SenderEmailAddress but its not giving me the sender's email id. It is giving me something like this -
/O=EXG5/OU=EXCHANGE ADMINISTRATIVE GROUP (FYDIBOHF23SPDLT)/CN=RECIPIENTS/CN=TEST35345

The address returned now is an (X.400) Exchange address.
Please take a look at this MSDN article on how to retrieve the corresponding SMTP address.

I am using this VBA routine to retrieve the SMTP address of a mailItem object:
(should be easily portable to C#)
Private Function getSmtpMailAddress(sMail As Outlook.mailItem) As String
Dim strAddress As String
Dim strEntryId As String
Dim objRecipient As Outlook.Recipient
Dim objSession As Outlook.NameSpace
Dim objAddressentry As Outlook.AddressEntry
Dim objExchangeUser As Outlook.ExchangeUser
Dim objReply As Outlook.mailItem
On Error GoTo ErrHandler
If sMail.SenderEmailType = "SMTP" Then
strAddress = sMail.SenderEmailAddress
Else
Set objReply = sMail.reply()
Set objRecipient = objReply.recipients.item(1)
strEntryId = objRecipient.EntryID
objReply.Close OlInspectorClose.olDiscard
Set objSession = getMapiSession
strEntryId = objRecipient.EntryID
Set objAddressentry = objSession.GetAddressEntryFromID(strEntryId)
Set objExchangeUser = objAddressentry.GetExchangeUser()
strAddress = objExchangeUser.PrimarySmtpAddress()
End If
getSmtpMailAddress = strAddress
Exit Function
ErrHandler:
Err.Clear
On Error GoTo 0
getSmtpMailAddress = "???"
End Function
This works for Outlook 2007. The MSDN solution for Outlook 2010 as pointed out above, looks a bit nicer.

Related

Can I somehow convert attachments I get from Outlook Add In to pdf?

I am currently making an Outlook Add In and I successfully got the attachments from an email.
Here is the attachment:
And here is the method:
public static List<AttachmentResponse> GetAttachments(
AttachmentSampleServiceRequest request)
{
// Create an ExchangeService object, set the credentials and the EWS URL.
var service = new ExchangeService
{
Credentials = new OAuthCredentials(request.AttachmentToken),
Url = new Uri(request.EwsUrl)
};
var result = new List<AttachmentResponse>();
var getAttachmentsResponse =
service.GetAttachments(request.Attachments.Select(attachment => attachment.id).ToArray(),
null,
new PropertySet(BasePropertySet.FirstClassProperties,
ItemSchema.MimeContent));
var getAttachmentResponsesFiltered = getAttachmentsResponse.Where(file =>
file.Result == ServiceResult.Success && file.Attachment.ContentType == "application/pdf");
{
result.AddRange(from attachmentResponse in getAttachmentResponsesFiltered
let fileAttachment = attachmentResponse.Attachment as FileAttachment
let base64String =
Convert.ToBase64String(fileAttachment?.Content, 0, (int) fileAttachment?.Content.Length)
select new AttachmentResponse
{
Id = attachmentResponse.Attachment.Id, Name = attachmentResponse.Attachment.Name,
Type = attachmentResponse.Attachment.ContentType, FileBase64 = base64String
});
}
return result;
}
The Open XML SDK which you could use on the server-side doesn't provide anything for generating PDF files. You may try to use something like iText or iTextSharp or any other third-party components designed for the server-side execution.
In case of COM add-ins there is no need to use EWS at all. Use the Attachments property of Outlook items to deal with attached files and items. The MailItem.Attachments property returns an Attachments object that represents all the attachments for the specified item. You can access attachments in the collection by using the either the index number of the object, or a value used to match the default property of an object in the collection. For example, here is a sample VBA code which illustrates how you could use the Outlook object model from your add-in:
Sub SaveAttachment()
Dim myInspector As Outlook.Inspector
Dim myItem As Outlook.MailItem
Dim myAttachments As Outlook.Attachments
Set myInspector = Application.ActiveInspector
If Not TypeName(myInspector) = "Nothing" Then
If TypeName(myInspector.CurrentItem) = "MailItem" Then
Set myItem = myInspector.CurrentItem
Set myAttachments = myItem.Attachments
'Prompt the user for confirmation
Dim strPrompt As String
strPrompt = "Are you sure you want to save the first attachment in the current item to the Documents folder? If a file with the same name already exists in the destination folder, it will be overwritten with this copy of the file."
If MsgBox(strPrompt, vbYesNo + vbQuestion) = vbYes Then
myAttachments.Item(1).SaveAsFile Environ("HOMEPATH") & "\My Documents\" & myAttachments.Item(1).DisplayName
End If
Else
MsgBox "The item is of the wrong type."
End If
End If
End Sub

Fetching Outlook email body

I am trying to make a function that fetches the body of an email with a given search criteria. When I fetch items from the mailbox and try to get the body, it only writes part of the body. I want ALL text from the body instead. How can I do this? This is what I have so far:
Outlook.Application myApp = new Outlook.Application();
const string PR_HAS_ATTACH = "http://schemas.microsoft.com/mapi/proptag/0x0E1B000B";
// Obtain Inbox
Outlook.Folder folder = myApp.Session.GetDefaultFolder(OlDefaultFolders.olFolderInbox) as Microsoft.Office.Interop.Outlook.Folder;
Outlook.Table table = folder.GetTable(Microsoft.Office.Interop.Outlook.OlTableContents.olUserItems);
// Remove default columns
table.Columns.RemoveAll();
// Add using built-in name
table.Columns.Add("Subject");
table.Columns.Add("ReceivedTime");
table.Sort("ReceivedTime", Microsoft.Office.Interop.Outlook.OlSortOrder.olDescending);
// Add using namespace
// Date received
table.Columns.Add("urn:schemas:httpmail:textdescription");
while (!table.EndOfTable)
{
Outlook.Row row = table.GetNextRow();
if (row["Subject"].ToString().ToLower().Contains(subject.Text.ToLower()) && row["ReceivedTime"].ToString().Contains(cellCreationDate))
{
body.Text = row["urn:schemas:httpmail:textdescription"].ToString();
}
}
You can't use Outlook.Table and then urn:shcemas:httpmail.textdescription to get the entire body. textdescription only returns the first 255 characters of the body as noted here http://msdn.microsoft.com/en-us/library/office/ff861580.aspx.
here is an alternative.
// change this in your code
body.Text = row["urn:schemas:httpmail:textdescription"].ToString();
// To this
Microsoft.Office.Interop.Outlook.MailItem mailItem =
myApp.Session.GetItemFromID(row["EntryID"]);
body.Text = mailItem.Body;

How can I create a custom sortable field in Outlook populated by a formula?

Having successfully created a custom field in Outlook via a formula and parsing the Subject field; I have now hit a new snag. The custom field is not sortable. It appears as of current that the only way to achieve this is to create a new user property which would then be sortable and could be leveraged when defining the field.
The option also exists to push everything into either a VBA script or C# app using the interop. Either way would work for me however I would prefer to go the VBA route and keep it self contained.
The emails exist in a folder and can be ran after the fact; the solution does not need to remain constantly active.
If anyone could point me to code which can easily achieve this that would be great. If I am missing an option to make the custom field sortable then please provide the alternative as that is the end goal.
EDIT:
This is what I currently have...
Sub SortCustomField()
Dim olApp As Outlook.Application
Dim objLotusInbox As Outlook.MAPIFolder
Dim objLotusInboxItems As Outlook.Items
Dim objNameSpace As Outlook.NameSpace
Dim objProperty As Outlook.UserDefinedProperty
Set olApp = CreateObject("Outlook.Application")
Set objNameSpace = olApp.GetNamespace("MAPI")
Set objLotusInbox = objNameSpace.GetDefaultFolder(olFolderInbox).Folders("Lotus Notes Inbox")
Set objLotusInboxItems = objLotusInbox.Items
objLotusInboxItems.Sort "[Notes2Outlook Created]", False
Set objLotusInboxItems = Nothing
Set objLotusInbox = Nothing
Set objNameSpace = Nothing
Set olApp = Nothing
End Sub
Erroring out at the sort; pretty certain it is due to the fact that the stated field is a user defined field as it works on other fields such as From.
UPDATE:
Made some ground, however when going back to Outlook it does not appear to populate the field defined during the run.
Dim olApp As Outlook.Application
Dim objLotusInbox As Outlook.MAPIFolder
Dim objLotusInboxItems As Outlook.Items
Dim objNameSpace As Outlook.NameSpace
Dim objMailProperty As Outlook.UserProperty
Dim objMailItem As Outlook.MailItem
Dim objParsedDate As Date
Dim sample As Object
Set olApp = CreateObject("Outlook.Application")
Set objNameSpace = olApp.GetNamespace("MAPI")
Set objLotusInbox = objNameSpace.GetDefaultFolder(olFolderInbox).Folders("Lotus Notes Inbox")
Set objLotusInboxItems = objLotusInbox.Items
For Each objMailItem In objLotusInboxItems
Set objMailProperty = objMailItem.UserProperties.Add("MyUserProp", olDateTime)
objParsedDate = CDate(Mid(objMailItem.Subject, (InStr(objMailItem.Subject, "[") + 1), (InStr(objMailItem.Subject, "]") - InStr(objMailItem.Subject, "[")) - 1))
objMailProperty.Value = objParsedDate
Next
Set objLotusInboxItems = Nothing
Set objLotusInbox = Nothing
Set objNameSpace = Nothing
Set olApp = Nothing
I was having the same problem using c# and Add-in-express VSTO addin.
I solved it by saving the MailItem object after I has made the property change.
So for your code I would do the following:objMailItem.Save at the pertinent point. Namely at the end of each iteration of the For loop.
NB: In my c# code I use Marshal.ReleaseComObject for the USerProperty assigned object.
Since you are populating it in the VBA already you should be able to change the User-Property to a text field which can be sorted.
The method I use is running a script based on a rule but in your case you can call it as a sub in the for-each loop.
Sub SomeAction(Item As Outlook.MailItem)
Dim myProperty As Outlook.UserProperty
Set myProperty = Item.UserProperties.Add("MyUserProp", olText, True)
myProperty.Value = Mid(objMailItem.Subject, (InStr(objMailItem.Subject, "[") + 1), (InStr(objMailItem.Subject, "]") - InStr(objMailItem.Subject, "[")) - 1))
Item.Save
Set myProperty = Nothing
End Sub
Only thing left to do is add a user defined column in your view which is a Text based user defined field.
note, since you are using a Date/Time item, this method should work just as well when you define the UserProperty as olDateTime
I've combined the answers from above to add a user defined column which is populated by running a rule selecting the script. I can then sort my inbox by the senders domain. My thanks to the previous contributors.
Public Sub SortByDomain(oMsg As Outlook.MailItem)
On Error Resume Next
Dim sDomain As String 'The Sender's domain
Dim oNS As Outlook.NameSpace 'My namespace
Dim oInbox As Outlook.MAPIFolder 'My Inbox
Dim oTarget As Outlook.MAPIFolder 'The domain folder
Dim myProperty As Outlook.UserProperty
'If it's not your domain, decipher the domain.
If InStr(oMsg.SenderEmailAddress, "mydomain.com") < 1 Then
sDomain = Mid(oMsg.SenderEmailAddress, InStr(oMsg.SenderEmailAddress, "#") + 1)
Else
sDomain = "mydomain.com"
End If
Set myProperty = oMsg.UserProperties.Add("SenderDomain", olText, True)
myProperty.Value = sDomain
oMsg.Save
'Cleanup.
Set oTarget = Nothing
Set oInbox = Nothing
Set oNS = Nothing
Set myProperty = Nothing
End Sub

Send already generated MHTML using CDOSYS through C#?

I have a ready generated MHTML as a byte array (from Aspose.Words) and would like to send it as an email. I'm trying to do this through CDOSYS, though am open to other suggestions. For now though I have the following:
CDO.Message oMsg = new CDO.Message();
CDO.IConfiguration iConfg = oMsg.Configuration;
Fields oFields = iConfg.Fields;
// Set configuration.
Field oField = oFields["http://schemas.microsoft.com/cdo/configuration/sendusing"];
oField.Value = CDO.CdoSendUsing.cdoSendUsingPort;
oField = oFields["http://schemas.microsoft.com/cdo/configuration/smtpserver"];
oField.Value = SmtpClient.Host;
oField = oFields["http://schemas.microsoft.com/cdo/configuration/smtpserverport"];
oField.Value = SmtpClient.Port;
oFields.Update();
//oMsg.CreateMHTMLBody("http://www.microsoft.com", CDO.CdoMHTMLFlags.cdoSuppressNone, "", "");
// NEED MAGIC HERE :)
oMsg.Subject = warning.Subject; // string
oMsg.From = "system#example.com";
oMsg.To = warning.EmailAddress;
oMsg.Send();
In this snippet, the warning variable has a Body property which is a byte[]. Where it says "NEED MAGIC HERE" in the code above I want to use this byte[] to set the body of the CDO Message.
I have tried the following, which unsurprisingly doesn't work:
oMsg.HTMLBody = System.Text.Encoding.ASCII.GetString(warning.Body);
Anybody have any ideas how I can achieve what I want with CDOSYS or something else?
Please don't use CDO, it dates from an era when computers still used smoke signals to exchange emails. System.Net.Mail contains everything you need, MailMessage is your friend. Note its IsBodyHtml property.
It is possible via CDO.Message (it is necessary add to project references COM library "Microsoft CDO for Windows 2000 Library"):
protected bool SendEmail(string emailFrom, string emailTo, string subject, string MHTmessage)
{
string smtpAddress = "smtp.email.com";
try
{
CDO.Message oMessage = new CDO.Message();
// set message
ADODB.Stream oStream = new ADODB.Stream();
oStream.Charset = "ascii";
oStream.Open();
oStream.WriteText(MHTmessage);
oMessage.DataSource.OpenObject(oStream, "_Stream");
// set configuration
ADODB.Fields oFields = oMessage.Configuration.Fields;
oFields("http://schemas.microsoft.com/cdo/configuration/sendusing").Value = CDO.CdoSendUsing.cdoSendUsingPort;
oFields("http://schemas.microsoft.com/cdo/configuration/smtpserver").Value = smtpAddress;
oFields.Update();
// set other values
oMessage.MimeFormatted = true;
oMessage.Subject = subject;
oMessage.Sender = emailFrom;
oMessage.To = emailTo;
oMessage.Send();
}
catch (Exception ex)
{
// something wrong
}
}

Are there any Outlook Contacts Controls in ASP.NET?

How can I access Microsoft Outlook contacts using ASP.NET? Are there any controls that can do this?
If by control you mean api, there already is one - Exchange Web Services (EWS). Assuming you are dealing with exchange, and have EWS set up. The web services usually sit at:
https://[yourmaildomain.com]/EWS/Exchange.asmx
Here is some quick code - not production tested (also in vb.net)
Dim esb As New ExchangeServiceBinding()
esb.Credentials = New NetworkCredential("someusername", "somepassword")
esb.Url = "https://[yourmaildomain.com]/EWS/Exchange.asmx"
Dim addressType As New EmailAddressType()
With addressType
.EmailAddress = "email#domain.com"
.MailboxType = MailboxTypeType.Mailbox
.MailboxTypeSpecified = True
End With
' properties
Dim itemProperties As New ItemResponseShapeType()
itemProperties.BaseShape = DefaultShapeNamesType.AllProperties
' Identify which folders to search to find items.
Dim folderIDs(0) As DistinguishedFolderIdType
folderIDs(0) = New DistinguishedFolderIdType()
folderIDs(0).Id = DistinguishedFolderIdNameType.contacts
folderIDs(0).Mailbox = addressType
Dim findItemRequest As New FindItemType()
findItemRequest.Traversal = ItemQueryTraversalType.Shallow
findItemRequest.ItemShape = itemProperties
findItemRequest.ParentFolderIds = folderIDs
' send request
Dim findItemResponse As FindItemResponseType = esb.FindItem(findItemRequest)
Dim rmta As ResponseMessageType() = findItemResponse.ResponseMessages.Items
For Each rmt As ResponseMessageType In rmta
If rmt.ResponseClass = ResponseClassType.Success Then
Dim firmt As FindItemResponseMessageType = CType(rmt, FindItemResponseMessageType)
If firmt IsNot Nothing Then
Dim root As FindItemParentType = firmt.RootFolder
Dim obj As Object = root.Item
If TypeOf obj Is ArrayOfRealItemsType Then
Dim items As ArrayOfRealItemsType = DirectCast(obj, ArrayOfRealItemsType)
If items.Items IsNot Nothing Then
For Each it As ItemType In items.Items
If TypeOf it Is ContactItemType Then
Dim cit As ContactItemType = DirectCast(it, ContactItemType)
Response.Write("<p>")
Response.Write(cit.Subject)
Response.Write("<p>")
End If
Next
End If
End If
End If
End If
Next
FROM Microsoft Support:
How to use the Microsoft Outlook Object Library to retrieve a contact by using Visual C#
MSDN:
Outlook Object Model Overview
How to: Access Outlook Contacts (Some more nice how to's at the end)
You would need to create an ActiveX Application that the client would install to allow you access to this. Unless it's an internal development project, don't expect people to install something that gives you access to their email program.

Categories