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.