Giter VIP home page Giter VIP logo

Comments (31)

bmullen-steelcase avatar bmullen-steelcase commented on June 6, 2024 2

If anyone else comes across this, forcing a complete uninstall and reinstall did fix the problem. Thanks!

from exchangelib.

ecederstrand avatar ecederstrand commented on June 6, 2024 1

I added initial support the the above objects and services, but I don't have time right now to come up with a nice Pythonic API for handling attachments, plugging the parts together, testing etc. If you want, you can give it a go.

Beware that the service call() methods (e.g. exchangelib.services.GetAttachment.call()) fail ATM because I haven't completed the response XML translation to Python objects (done by finding attachment elements in the response and calling e.g. exchangelib.folders.FileAttachment.from_xml()).

from exchangelib.

ecederstrand avatar ecederstrand commented on June 6, 2024 1

See https://github.com/ecederstrand/exchangelib/blob/master/CHANGELOG.rst for example usage. Please let me know if there are any issues :-)

from exchangelib.

nstr10 avatar nstr10 commented on June 6, 2024 1

It works! Thank you so much! You have no idea how excited I am about this!!! :)

from exchangelib.

nstr10 avatar nstr10 commented on June 6, 2024 1

Sorry, didn't see that update! I re-cloned and the issue is resolved. Thanks! :)

from exchangelib.

ecederstrand avatar ecederstrand commented on June 6, 2024

It's not a planned feature ATM. This would require supporting the item:Attachments attribute on Item, plus FileAttachment and ItemAttachment objects, plus the GetAttachment, CreateAttachment and DeleteAttachment services.

None of these should be difficult to implement, though. Patches welcome :-)

from exchangelib.

nstr10 avatar nstr10 commented on June 6, 2024

I'll see what I can do, and if I get something working will submit a pull request.

Thank you for the prompt reply.

from exchangelib.

nstr10 avatar nstr10 commented on June 6, 2024

I've tried a few times to get started on this, but am having a hard time understanding how I'm even supposed to call methods like exchangelib.services.GetAttachment.call() -- no matter what argument I pass to it, I get back errors, for example:

File "exchangelib/services.py", line 811, in call
    elements = super().call(**kwargs)
TypeError: super(type, obj): obj must be an instance or subtype of type

I had to comment out lines 809-810 as they aren't relevant to my environment and also threw errors no matter what I tried (e.g. map has no property protocol).
This library is far beyond my ability to comprehend. I've learned a lot in trying to, but haven't actually made any progress toward getting these methods to work. Any chance you could provide some more basic information, like what these methods might expect as arguments?

from exchangelib.

ecederstrand avatar ecederstrand commented on June 6, 2024

I'm sorry. My previous example was incorrect. GetAttachment should be called like this: exchangelib.services.GetAttachment(account=my_account).call(items=[('itemid1', 'changekey1'), ('itemid2', 'changekey2'), ...]). It will throw an AssertionError since the part of the code that convert from XML to FileAttachment class instances is not implemented. Most likely, the FileAttachment class is not complete, either.

from exchangelib.

nstr10 avatar nstr10 commented on June 6, 2024

Thanks! I'm getting different errors now, which I'll take as a sign of progress! :)

from exchangelib.

ecederstrand avatar ecederstrand commented on June 6, 2024

Cool! FileAttachment.content needs some thought - it will contain the actual file contents. How does one work painlessly with attachments - creating, fetching, modifying, storing to disk etc? Here are some ideas:

# Creating a new message
my_message = Message(...)
# 'content' could accept any file-like object. This is very flexible, and we can avoid loading data into memory until the XML is created.
with open('/path/to/file.png') as f:
    my_message.attachments.add(FileAttachment(name='my_picture.png', content=f))
my_message.attachments.add(FileAttachment(name='my_data.dat', content=io.BytesIO(b"some initial binary data: \x00\x01")))
my_message.attachments.add(FileAttachment(name='my_notes.txt', content=io.BytesIO("Remember the milk".encode('utf-8'))))
my_message.send()
# Receiving a new message
some_message = my_inbox.filter(subject="I'd Like to Add you to My Professional Network on LinkedIn")[0]
# Saving contents to disk
for a in some_message.attachments:
    a.save(os.path.join('/tmp', a.name))
# Or maybe this
for a in some_message.attachments:
    with file.open(os.path.join('/tmp', a.name), 'wb') as f:
        f.write(a.content)

from exchangelib.

nstr10 avatar nstr10 commented on June 6, 2024

My instincts say the library should simply return a memory reference to the binary, as storing in /tmp or similar will mean this can't be used on platforms that don't have a /tmp (Windows comes to mind). That said, I haven't reviewed the whole code base so maybe this is already platform-specific?

from exchangelib.

ecederstrand avatar ecederstrand commented on June 6, 2024

I agree that dumping to disk should be avoided. The autodiscover code writes to a file-based cache, but apart from that nothing touches the disk.

from exchangelib.

nstr10 avatar nstr10 commented on June 6, 2024

Was getting error generator object has no attribute 'iter' from util.py xml_to_str function which seemed to indicate it was being sent the wrong thing. Changing services.py GetAttachment.call to call xml_to_str for each element in elements seems to get a little farther, but I get "The Id does not represent an item attachment."
Am I way off course with this? I don't see anything attachment-related in the response to inbox.fetch, so I was passing the response from inbox.find_items instead... I have a feeling I'm doing this entirely wrong since I haven't gotten to the assertion error you mentioned.

from exchangelib.

ecederstrand avatar ecederstrand commented on June 6, 2024

Can you post your code somewhere? That would make it a bit easier to understand what you're doing.

from exchangelib.

nstr10 avatar nstr10 commented on June 6, 2024

Here's what I'm working with:
http://pastebin.com/2msfGsRn

Most of it works fine, so I might be able to simplify it a bit further. Tried to remove as much superfluous code as possible.

I've tried a few different ways of calling GetAttachment().call() and GetAttachment() with various inputs that are available, but haven't had any success.

from exchangelib.

ecederstrand avatar ecederstrand commented on June 6, 2024

I won't have time to look at this before next week. Just leaving some examples of how the XML input and output should be structured:
https://msdn.microsoft.com/en-us/library/office/dn726695(v=exchg.150).aspx
https://msdn.microsoft.com/en-us/library/office/dn726694(v=exchg.150).aspx

from exchangelib.

nstr10 avatar nstr10 commented on June 6, 2024

Example usage doesn't seem to include how to get an attachment. I'm getting a generator object back from GetAttachment().call() and am not sure what to do with that object. Could you add an example of getting an attachment?

from exchangelib.

ecederstrand avatar ecederstrand commented on June 6, 2024

Ah, of course! I'll add that ASAP. Each item in a folder has an attachments attribute which is a list you can iterate over. Attribute content fetching is lazy, so the first access to some_attachment.content will generate a GetAttachment call transparently.

from exchangelib.

ecederstrand avatar ecederstrand commented on June 6, 2024

Support for item attachments (https://msdn.microsoft.com/en-us/library/office/aa562997(v=exchg.150).aspx) will hopefully be committed in the next days.

from exchangelib.

nstr10 avatar nstr10 commented on June 6, 2024

Before you commit, it looks like emails with .msg attachments break this -- and because of the lazy fetching, you don't have to actually do anything attachment-related for it to break. Should I submit that as an issue?

from exchangelib.

ecederstrand avatar ecederstrand commented on June 6, 2024

I committed ItemAttachment support yesterday (89cac30). If you're already running that version, can you please post code that reproduces this, or a stacktrace and an XML dump? Thanks

from exchangelib.

bmullen-steelcase avatar bmullen-steelcase commented on June 6, 2024

I've updated everything (as far as I can tell) but I'm getting 'Message' object has no attribute 'attachment' errors.

Here's my code.

for message in account.inbox.all():
    print("Received: ", message.datetime_received)
    print("Sender: ", message.sender.name)
    print("Email: ", message.sender.email_address)
    print("Reply To: ", message.reply_to)
    print("Subject: ", message.subject)
    print("\n", message.attachment)

Could someone tell me what I'm doing wrong?

from exchangelib.

ecederstrand avatar ecederstrand commented on June 6, 2024

It's 'attachments', not 'attachment' :-)

Did you find this in an example somewhere? In that case, please send a link so I can update it.

from exchangelib.

bmullen-steelcase avatar bmullen-steelcase commented on June 6, 2024

First off, that's very embarrassing. lol

But even correcting "attachments" it's still not working. No attribute.

For the record, I reinstalled exchangelib from a fresh download using setup.py install --force to make sure I was overwriting my copy of the package from a few days ago.

from exchangelib.

bmullen-steelcase avatar bmullen-steelcase commented on June 6, 2024

Running dir() on a message I get this:
['CHOICES', 'ELEMENT_NAME', 'EXTENDED_PROPERTIES', 'FIELDURI_PREFIX', 'ITEM_FIELDS', 'ORDERED_FIELDS', 'READONLY_AFTER_SEND_FIELDS', 'READONLY_FIELDS', 'REQUIRED_FIELDS', 'SUBJECT_MAXLENGTH', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '__weakref__', '_delete', '_save', 'account', 'additional_property_elems', 'bcc_recipients', 'body', 'categories', 'cc_recipients', 'changekey', 'choices_for_field', 'complex_fields', 'datetime_created', 'datetime_received', 'datetime_sent', 'delete', 'deregister', 'elem_for_field', 'extern_id', 'fieldnames', 'fielduri_for_field', 'folder', 'from', 'from_xml', 'id_from_xml', 'importance', 'is_delivery_receipt_requested', 'is_draft', 'is_read', 'is_read_receipt_requested', 'is_response_requested', 'item_id', 'last_modified_name', 'last_modified_time', 'move', 'move_to_trash', 'ordered_fieldnames', 'readonly_after_send_fields', 'readonly_fields', 'refresh', 'register', 'reminder_is_set', 'reply_to', 'request_tag', 'required_fields', 'response_tag', 'response_xml_elem_for_field', 'save', 'send', 'send_and_save', 'sender', 'sensitivity', 'set_field_xml', 'soft_delete', 'subject', 'to_recipients', 'to_xml', 'type_for_field', 'uri_for_field']

Am I not getting the newest build?

from exchangelib.

ecederstrand avatar ecederstrand commented on June 6, 2024

The output doesn't help, unfortunately.

This is almost definitely an installation issue. Try pip3 uninstall exchangelib and pip3 install exchangelib==1.7.3. If that still doesn't work, probably pip is installing to another location that your script is importing from. Try this from your script:

print(exchangelib.__file__)

That will show you the location of the sources. Delete the sources manually (rm -r /path/to/site-packages/exchangelib*) if pip uninstall exchangelib doesn't remove them for some reason.

from exchangelib.

ocgariando avatar ocgariando commented on June 6, 2024

many thanks ecederstrand

from exchangelib.

MartinThoma avatar MartinThoma commented on June 6, 2024

Here is how you read all emails and download the attachments with exchangelib: https://stackoverflow.com/a/45438174/562769

from exchangelib.

srikkar avatar srikkar commented on June 6, 2024

Please help on replying an email with attachments, where the reply must be saved in the sent items folder.

I'm able to send attachments in a new mail.

m = Message(
     account=account,
     folder=account.sent,
     subject='Daily motivation',
     body='xxxx is awesome... Said by xxxx',
     to_recipients=['xx.Varun@xxx', 'xxx@xxx']
  )
  # attach files
  for attachment_name, attachment_content in output or []:
     file = FileAttachment(name=attachment_name, content=attachment_content)
     m.attach(file)    
  m.send_and_save()   

from exchangelib.

ecederstrand avatar ecederstrand commented on June 6, 2024

The Message.reply() method creates and sends a ReplyToItem item which doesn't support attachments. See https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/replytoitem

So if you want to send a reply that has attachments, just create a normal Message item that has a 'Re: some subject' title, contains the attachment, and quotes the original message, if that's needed.

from exchangelib.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.