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

2

6

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()
Chattanooga answered 5/11, 2014 at 4:25 Comment(0)
B
2

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)

Bilateral answered 25/3, 2018 at 22:19 Comment(0)
R
1

The older android module has support for passing a filename. You could use this directly, or add the feature to plyer via calling the relevant parts of the android api. I don't reember exactly how you do that though.

Revolting answered 5/11, 2014 at 11:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.