To send an email from your app with an attachment like image, video, etc. We can do this by calling 2-3 functions.

First, we need to add some required permission in AndroidManifest.xml as below.

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Then add necessary dependency as below,

implementation 'com.google.android.gms:play-services-auth:17.0.0'
implementation('com.google.api-client:google-api-client-android:1.23.0') {
    exclude group: 'org.apache.httpcomponents'
}
implementation('com.google.apis:google-api-services-gmail:v1-rev82-1.23.0') {
    exclude group: 'org.apache.httpcomponents'
}
implementation files('libs/mail.jar')
implementation files('libs/activation.jar')
implementation files('libs/additionnal.jar')

You can download the above .jar file from below link,

https://code.google.com/archive/p/javamail-android/downloads

Now write code to  create Mail with attachment as below,

// Method to create email Params
@Throws(MessagingException::class)
private fun createEmail(
    to: List<String>,
    from: String,
    subject: String,
    bodyText: String
): MimeMessage? {
    val props = Properties()
    val session: Session = Session.getDefaultInstance(props, null)
    val email = MimeMessage(session)
    val fAddress = InternetAddress(from)
    email.setFrom(fAddress)

    to.forEachIndexed { index, s ->
        val tAddress = InternetAddress(s)
        email.addRecipient(javax.mail.Message.RecipientType.TO, tAddress)
    }


    email.subject = subject
    // Create Multipart object and add MimeBodyPart objects to this object
    val multipart: Multipart = MimeMultipart()
    // Changed for adding attachment and text
    email.setText(bodyText)
    val textBody: BodyPart = MimeBodyPart()
    textBody.setText(bodyText)

    multipart.addBodyPart(textBody)
    if (fileName != "") { // Create new MimeBodyPart object and set DataHandler object to this object
        val attachmentBody = MimeBodyPart()
        val filename: String = fileName // change accordingly
        val source = FileDataSource(filename)
        attachmentBody.dataHandler = DataHandler(source)
        attachmentBody.fileName = filename
        multipart.addBodyPart(attachmentBody)
    }

    //Set the multipart object to the message object
    email.setContent(multipart)
    return email
}

Then, create a message to send in email,

@Throws(MessagingException::class, IOException::class)
private fun createMessageWithEmail(email: MimeMessage): Message? {
    val bytes = ByteArrayOutputStream()
    email.writeTo(bytes)
    val encodedEmail: String = Base64.encodeBase64URLSafeString(bytes.toByteArray())
    val message = Message()
    message.raw = encodedEmail
    return message
}

Finally, send mail. Here you have to run send mail code in the background thread. For that, I have used doAsync of Anko library(Extension of Coroutines).

Dependency for Anko :

implementation "org.jetbrains.anko:anko-commons:0.10.0"
private fun sendEmail() {
        var mService: Gmail? = null
        var mLastError = null

        val transport = AndroidHttp.newCompatibleTransport()
        val jsonFactory = JacksonFactory.getDefaultInstance()

        mService = Gmail.Builder(
            transport, jsonFactory, mCredential
        ).setApplicationName(resources.getString(R.string.app_name))
            .build()


        // getting Values for to Address, from Address, Subject and Body
        val user = "me"
        val to = etEmail.text.trim().toString()
        val from = mCredential!!.selectedAccountName
        val subject = "DemoSubject"
        val body = "Demo body"
        var mimeMessage: MimeMessage? = null
        var response = ""

        val toArrayList = to.split(",")

        doAsync {
            try {
                mimeMessage = createEmail(toArrayList, from, subject, body)

                var message = createMessageWithEmail(mimeMessage!!)

//                GMail's official method to send email with oauth2.0
                message = mService.users().messages().send(user, message).execute()

                runOnUiThread {
                    if (message.id != null && message.id != "") {
                        Toast.makeText(
                            this@MainActivity,
                            "Mail sent successfully",
                            Toast.LENGTH_SHORT
                        )
                            .show()
                    }
                }

                println("Message id: " + message.id)
                println(message.toPrettyString())

            } catch (e: UserRecoverableAuthIOException) {
                startActivityForResult(e.intent, REQUEST_AUTHORIZATION)
            } catch (e: GoogleJsonResponseException) {
                runOnUiThread {
                    if (e.details.errors[0].domain.equals("global", true)) {
                        Toast.makeText(
                            this@MainActivity,
                            "Mail not send, Please use Gmail id",
                            Toast.LENGTH_SHORT
                        )
                            .show()
                    } else {
                        Toast.makeText(this@MainActivity, "Can't send mail", Toast.LENGTH_SHORT)
                            .show()
                    }
                }
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }

Now, set UI component,

btnSendEmail.setOnClickListener {
    if (!isGooglePlayServicesAvailable()) {
        acquireGooglePlayServices()
    } else {
        startActivityForResult(
            mCredential!!.newChooseAccountIntent(),
            REQUEST_ACCOUNT_PICKER
        )
    }
}

Call sendMail() function from onActivityResult.

You can find full demo code from below link,

https://github.com/android-inheritx/SendMailUsingGmailAPI

Note : You can send mail from the “gmail.com” domain only.

 

 

You may also like

Leave a Reply