Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Send email with attachment from Kivy app on Android, preferably by opening email client

I have tried a few ways to send an email using Python in the Kivy app on Android. The closest I've come is using Plyer's email function (https://plyer.readthedocs.org/en/latest/#plyer.facades.Email), however it doesn't appear to support attachments.

What I want my app to do is open the user's email client and populate the recipient, subject, body and attachment fields. The attachment will be a .csv file generate by my app.

Does anyone have suggestions on how to do this? How can I modify this code to include attachments?

from jnius import autoclass, cast
from plyer.facades import Email
from plyer.platforms.android import activity

Intent = autoclass('android.content.Intent')
AndroidString = autoclass('java.lang.String')


class AndroidEmail(Email):
    def _send(self, **kwargs):
    intent = Intent(Intent.ACTION_SEND)
    intent.setType('text/plain')

    recipient = kwargs.get('recipient')
    subject = kwargs.get('subject')
    text = kwargs.get('text')
    create_chooser = kwargs.get('create_chooser')

    if recipient:
        intent.putExtra(Intent.EXTRA_EMAIL, [recipient])
    if subject:
        android_subject = cast('java.lang.CharSequence',
                               AndroidString(subject))
        intent.putExtra(Intent.EXTRA_SUBJECT, android_subject)
    if text:
        android_text = cast('java.lang.CharSequence',
                            AndroidString(text))
        intent.putExtra(Intent.EXTRA_TEXT, android_text)

    if create_chooser:
        chooser_title = cast('java.lang.CharSequence',
                             AndroidString('Send message with:'))
        activity.startActivity(Intent.createChooser(intent,
                                                    chooser_title))
    else:
        activity.startActivity(intent)


def instance():
    return AndroidEmail()
like image 310
kitch6041 Avatar asked Nov 05 '14 04:11

kitch6041


1 Answers

I know this is an old question but I was trying to solve this exact issue for a while and came up with a solution, hopefully this can save someone else some time in the future:

from jnius import autoclass, cast
from plyer.platforms.android import activity

def sendemail(self, **kwargs):
    Intent = autoclass('android.content.Intent')
    AndroidString = autoclass('java.lang.String')
    Uri = autoclass('android.net.Uri')
    File = autoclass('java.io.File')

    intent = Intent(Intent.ACTION_SEND)
    intent.setType('*/*')

    recipient = kwargs.get('recipient')
    subject = kwargs.get('subject')
    text = kwargs.get('text')
    create_chooser = kwargs.get('create_chooser')
    file_to_attach = kwargs.get('file_to_attach')

    if recipient:
        intent.putExtra(Intent.EXTRA_EMAIL, [recipient])
    if subject:
        android_subject = cast('java.lang.CharSequence',
                               AndroidString(subject))
        intent.putExtra(Intent.EXTRA_SUBJECT, android_subject)
    if text:
        android_text = cast('java.lang.CharSequence',
                            AndroidString(text))
        intent.putExtra(Intent.EXTRA_TEXT, android_text)

    if file_to_attach:
        attachment = File('path/to/your/file/' + file_to_attach)
        uri = Uri.fromFile(attachment)
        parcelable = cast('android.os.Parcelable', uri)
        intent.putExtra(Intent.EXTRA_STREAM, parcelable)

    if create_chooser:
        chooser_title = cast('java.lang.CharSequence',
                             AndroidString('Send message with:'))
        activity.startActivity(Intent.createChooser(intent,
                                                    chooser_title))

    else:
        activity.startActivity(intent)

So from the email section of the Android common intents guide it shows that Intent.EXTRA_STREAM is how an attachment can be sent, and after looking at the code from a similar question here a few more additions from that code to the Plyer email code took care of the need to get an attachment attached to the email from my app.

The notable additions were:

Uri = autoclass('android.net.Uri') File = autoclass('java.io.File')

changing the intent.setType to: ('*/*') to accept files and not just text,

adding the file_to_attach = kwargs.get('file_to_attach') line to get the file from the function call,

and finally:

if file_to_attach:
    attachment = File('path/to/your/file/' + file_to_attach)
    uri = Uri.fromFile(attachment)
    parcelable = cast('android.os.Parcelable', uri)
    intent.putExtra(Intent.EXTRA_STREAM, parcelable)

to attach the file to the email.

Then in your function call just make sure to include the file_to_attach argument: sendemail(recipient='[email protected]',subject='subject',text='some text',file_to_attach='a_file.csv',create_chooser=True)

like image 161
TKuam Avatar answered Sep 27 '22 19:09

TKuam