How to download the Contact attached in an email using EWS API? - exchange-server

When attachment is Email I could simply get the mime content and save it. But when the attachment is Contact I am not able to get the MimeContent. Here is the code
itemAttachment.Load(new PropertySet(ItemSchema.MimeContent));
MimeContent mc = itemAttachment.Item.MimeContent;
//Convert it to bytes
byte[] contentBytes = mc.Content;
When attachment is contact I am getting below exception
Microsoft.Exchange.WebServices.Data.ServiceResponseException occurred
HResult=-2146233088 Message=MIME conversion is not supported for
this item type. Source=Microsoft.Exchange.WebServices StackTrace:
at Microsoft.Exchange.WebServices.Data.ServiceResponse.InternalThrowIfNecessary()
at Microsoft.Exchange.WebServices.Data.ServiceResponse.ThrowIfNecessary()
at Microsoft.Exchange.WebServices.Data.MultiResponseServiceRequest1.Execute()
at Microsoft.Exchange.WebServices.Data.ExchangeService.InternalGetAttachments(IEnumerable1
attachments, Nullable1 bodyType, IEnumerable1 additionalProperties,
ServiceErrorHandling errorHandling)
at Microsoft.Exchange.WebServices.Data.ExchangeService.GetAttachment(Attachment
attachment, Nullable1 bodyType, IEnumerable1 additionalProperties)
at Microsoft.Exchange.WebServices.Data.Attachment.InternalLoad(Nullable1
bodyType, IEnumerable1 additionalProperties)
at Microsoft.Exchange.WebServices.Data.ItemAttachment.Load(IEnumerable`1
additionalProperties)
at Presensoft.JournalEmailVerification.EmailVerification.DownloadFailedAttachments(EmailMessage
msg, JournalEmail journalEmail) in C:\Users\sameer\Presensoft\Email
Archiving\Presensoft.JournalEmailVerification\EmailVerification.cs:line
605 InnerException:
What is the proper way to download and save Contact attachment?

Saving as a contact in Exchange
Using MimeContent on a contact will not work because the server does not support the conversion. You can get MimeContent for a contact, you just can't save MimeContent as a contact.
Unfortunately there is no easy way to save an attached contact. What I would suggest is to manually clone the contact. Using EWS Managed API you can access the ItemAttachment as a contact. You would then need to create a new contact on the server, copy all the properties from the attached contact to the new contact using TryGetProperty(), then save the new contact.
I know it would make sense to just use the Save method on the contact object when you access the ItemAttachment. The problem is that there is a read only property on the object, IsAttachment, that is set to true and will not allow the object to be saved. If you try you will get an exception that this method is not available for attachments.
Saving as a .vcf file
If you are trying to save the contact to your local file system there are just a couple lines of code necessary.
itemAttachment.Load(ItemSchema.MimeContent);
File.WriteAllBytes("Contact.vcf", itemAttachment.Item.MimeContent.Content);
I hope this information helps. If this does resolve your problem, please mark the post as answered.
Thanks,
--- Bob ---

Related

Delete "Other Contact" using Python with Google People API

I used Google People API v1.otherContacts.copyOtherContactToMyContactsGroup (reference) to copy a contact from "Other Contacts" to "myContacts" contact group. I now want to delete the original contact from "Other Contacts" using the same API.
REST Resource v1.otherContacts (reference) does not list a DELETE action.
I tried using v1.people.deleteContact (reference) passing the resource name of my "Other Contact":
import pickle
from googleapiclient.discovery import build
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
people_api = build('people', 'v1', credentials=creds)
people_service = people_api.people()
response = people_service.deleteContact(resourceName='otherContacts/c1971897568350947161').execute()
But I got an error saying:
TypeError: Parameter "resourceName" value "otherContacts/c1971897568350947161" does not match the pattern "^people/[^/]+$"
Looks like v1.people.deleteContact does not work for deleting a contact in "Other Contacts".
How can I programmatically delete a contact from "Other Contacts"?
EDIT: Based on #DaImTo's suggestion below, I tried replacing otherContacts/ in the resource name with people/ and invoking the v1.people.deleteContact API, but I got an error saying:
googleapiclient.errors.HttpError: <HttpError 404 when requesting https://people.googleapis.com/v1/people/c1971897568350947161:deleteContact?alt=json returned " generic::NOT_FOUND: Contact person resources are not found.". Details: "[{'#type': 'type.googleapis.com/google.rpc.BadRequest', 'fieldViolations': [{'field': 'resourceNames[0]', 'description': 'Resource not found.'}]}]">
I advice consulting the documentation for people.deleteContact
Required. The resource name of the contact to delete.
DELETE https://people.googleapis.com/v1/{resourceName=people/*}:deleteContact
That means it should be people/c1971897568350947161 assuming that is the id of the user you want to delete c1971897568350947161.
Looks like Other Contacts are read only, according to this announcement from Google: https://developers.google.com/contacts/v3/announcement
The new People API has the same functionality as the legacy Contacts
API for all features, with the following exceptions for “Other
Contacts”:
Administrators have read-only permissions for “Other Contacts” through
the new scope. As sending mutate/write signals back to “Other
Contacts” is not supported, your users will have to add the Other
Contact as a My Contact if they wish to update its data fields.

Outlook Add-in file reading from mail

I am working on a Outlook add-in. I am not able to use the method item.getAttachmentsAsync in my plugin code to load and read the content of files.
I am getting ERROR TypeError: item.getAttachmentsAsync is not a function in run time.
var item = Office.context.mailbox.item;
var options = {asyncContext: {currentItem: item}};
item.getAttachmentsAsync(options, this.callback);
My requirement is explained below,
In the plugin we have a form and few fields are populated from mail body.
And I need mail attachments to auto upload to Form.
Please suggest a better way to do that.
using getAttachmentContentAsync I am able to get the file as a blob. but the problem is we need to call this method as soon after the mail opening. otherwise getting cors error

How to send an email with multiple attachments from Gmail using API client library for .NET

My app uses Google API client library for .NET to send emails with attachments.
When using Send(), I'm facing some limitations when it comes to file size of the attachments. So, I guess switching to Resumable upload as upload method may help. But it's pretty much undocumented.
Looking into source code, I guess using different Send() overload may be the way forward, but I can't figure out how to use it properly.
So, instead of attaching the files into message and calling it like this:
var gmailResult = gmail.Users.Messages.Send(new Message
{
Raw = base64UrlEncodedMessage
}, "me").Execute();
I should not attach the files to message and do something like following?
var gmailResult = gmail.Users.Messages.Send(new Message
{
Raw = base64UrlEncodedMessage
}, "me", fileStream, contentType).Upload();
The second version does not return any API error, but does nothing. I'm obviously missing something here.
How do I attach more than one attachment?
This is kind of an old question, but putting an answer here just in case anyone else needs it:
I was able to achieve this by converting my mime message into a stream (attachment(s) included), and then calling this overload on Send:
UsersResource.MessagesResource.SendMediaUpload googleSendRequest = service.Users.Messages.Send(null, "youremail#gmail.com", mimeMessageStream, "message/rfc822");
IUploadProgress created = googleSendRequest.Upload();
This will upload all of the attachments with the email message content and then send it off. I was able to send two 5 megabyte attachments in an email. Previously I was not able to send even one of those via the other Send method that takes in a base64 encoded mime message.

VSTO (Outlook) is forcing MSG attachments to be of olEmbeddeditem type, but olByValue needed

I need to send email with .msg file attached to Lotus Notes (Domino) by using VSTO (from Outlook Add-In). When this file is received in Lotus Notes, the email body from msg file is appended to the end of the main mail.
From this problem I am assuming that the issue is in attachment type.
I am trying to set the attachment type to by olByValue by adding attachment :
mail.Attachments.Add(msgFilePath, OlAttachmentType.olByValue, 0, displayName);
but whatever type I specify, it is still set to olEmbeddeditem.
Is there any way, how to force msg attachment to be olByValue?
Thank you for any suggestion or advise.
Have a nice day.
Note: For reference I have created email in Lotus-Notes too with msg attached, sent to Outlook and than forwarded back to Lotus-Notes and msg is attached not appended to the end.
There is not much you can do in the Outlook Object Model - it always tries to be "helpful" and converts MSG files to embedded message attachments. If using Redemption is an option (I am its author), it will not change the type:
SafeMailItem sItem = new SafeMailItem();
sItem.Item = mail;
sItem.Attachments.Add(msgFilePath);

Accessing Exchange account message store

I am trying to access the message store of an Exchange account.
I am using MAPI. The IMsgStore object is initialized using IMAPISession::OpenMsgStore.
The problem is that when using Exchange Cached Mode, the root folder for the 'Inbox' and Sent' is IPM_SUBTREE, while for online mesage store it is Top of Information Store.
How can I tell if the message store is located online or it is a local file path ?
I would like to be able to tell that from IMsgStore.
And another thing, do I have to supply the MDB_ONLINE to the IMAPISession::OpenMsgStore call if the message store is online?
This is how it looks now:
hRes = lpSession->OpenMsgStore( NULL,
storeEntryID.cb,
(LPENTRYID) storeEntryID.lpb,
&IID_IMsgStore,
/*MDB_ONLINE | */MDB_WRITE,
(LPMDB *)&msgStore);
Outlook 2010
Check the PR_STORE_OFFLINE property (true for OST, false for online online store).
EDIT
Use Store.PropertyAccessor.GetProperty. PR_STORE_OFFLINE property DASL name is
http://schemas.microsoft.com/mapi/proptag/0x6632000B

Resources