Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

SMailTM is a Lightweight Kotlin for https://mail.tm API (A Temp Mail Service) Easy to Use and Automate things (Open-Source)

License

Notifications You must be signed in to change notification settings

samyak2403/SMailTM

Open more actions menu

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

13 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

SMailTM - Kotlin Mail.tm API Wrapper

JitPack Kotlin API License Mail.tm

SMailTM is a powerful Kotlin library for Android that enables you to create and manage temporary disposable email addresses using the Mail.tm service. Perfect for protecting user privacy, testing, and avoiding spam.

🎯 What Does This Library Do?

This library allows you to:

  • βœ‰οΈ Create temporary email addresses instantly without registration
  • πŸ“₯ Receive emails in real-time with Server-Sent Events (SSE)
  • πŸ“Ž Download attachments from received emails
  • πŸ” Maintain user privacy - no personal information required
  • πŸš€ Build privacy-focused apps like temporary email services
  • πŸ§ͺ Test email functionality in your Android apps

Built specifically for Kotlin and Android, this library is a modern conversion of the popular JMailTM Java library, optimized with Kotlin Coroutines and Android best practices.

πŸ’‘ Use Cases

  • Privacy Protection Apps: Build apps like TempBox Lite for disposable emails
  • Email Testing: Test email verification flows in your apps
  • Sign-up Protection: Let users sign up without exposing their real email
  • Spam Prevention: Avoid spam by using temporary emails for untrusted sites
  • Anonymous Communication: Enable anonymous email receiving
  • Development & QA: Test email features without real email accounts

πŸ“± Apps Using SMailTM

TempBox Lite - Disposable Email Shield

Get it on Google Play

TempBox Lite is a lightweight, ad-free temporary email app built with SMailTM library. Generate disposable email addresses instantly to protect your privacy and keep your inbox spam-free.

Key Features:

  • πŸš€ Instant temporary email generation
  • πŸ“¬ Real-time email receiving with attachments
  • πŸ”’ Complete privacy & anonymity (no registration required)
  • πŸͺΆ Lightweight & fast performance
  • πŸ“‹ Easy copy & QR code sharing
  • πŸ”„ Auto-refresh inbox
  • 🧹 Self-cleaning inboxes for security

Perfect for sign-ups, verifications, and protecting your personal email from spam!

Download TempBox Lite on Google Play


πŸ“‹ Table of Contents

✨ Features

  • πŸ“§ Account Management - Create, login, and delete temporary email accounts
  • πŸ“¨ Message Operations - Fetch, read, mark as seen, and delete messages
  • πŸ”” Real-time Notifications - Server-Sent Events (SSE) for instant message updates
  • πŸ“Ž Attachment Support - Download and save email attachments
  • 🌐 Domain Management - List and select from available email domains
  • πŸ” Token Authentication - Login with JWT tokens for persistent sessions
  • ⚑ Async Operations - Built-in asynchronous methods for better performance
  • 🎯 Kotlin-First - Designed for Kotlin with coroutines-friendly callbacks
  • πŸ›‘οΈ Type-Safe - Full Kotlin type safety with data classes
  • πŸ“± Android Optimized - Lightweight and efficient for mobile apps

πŸ“¦ Installation

Step-by-Step Installation Guide

Follow these steps to integrate SMailTM into your Android project:

Step 1: Add JitPack Repository

Option A: Using settings.gradle.kts (Recommended for newer projects)

Open your project's root settings.gradle.kts file and add JitPack repository:

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        google()
        mavenCentral()
        maven { url = uri("https://jitpack.io") }  // Add this line
    }
}

Option B: Using build.gradle.kts (For older projects)

Open your project's root build.gradle.kts file and add JitPack repository:

allprojects {
    repositories {
        google()
        mavenCentral()
        maven { url = uri("https://jitpack.io") }  // Add this line
    }
}

Step 2: Add the Dependency

Open your app module's build.gradle.kts (or build.gradle) file and add the SMailTM dependency:

For Kotlin DSL (build.gradle.kts):

dependencies {
    implementation("com.github.samyak2403:SMailTM:SMailTM-v1.0.1")
}

For Groovy DSL (build.gradle):

dependencies {
    implementation 'com.github.samyak2403:SMailTM:SMailTM-v1.0.1'
}

Latest Version: JitPack

Step 3: Add Internet Permissions

Open your AndroidManifest.xml file and add the required permissions:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    
    <!-- Add these permissions -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    
    <application>
        <!-- Your app content -->
    </application>
</manifest>

Step 4: Sync Your Project

Click "Sync Now" in Android Studio or run:

./gradlew build

Step 5: Verify Installation

Create a simple test to verify the library is working:

import com.samyak.smailtm.util.SMailBuilder

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        // Test library installation
        lifecycleScope.launch(Dispatchers.IO) {
            try {
                val mailTM = SMailBuilder.createDefault("testPassword123")
                mailTM.init()
                val account = mailTM.getSelf()
                
                withContext(Dispatchers.Main) {
                    Log.d("SMailTM", "βœ… Library working! Email: ${account.email}")
                }
            } catch (e: Exception) {
                withContext(Dispatchers.Main) {
                    Log.e("SMailTM", "❌ Error: ${e.message}")
                }
            }
        }
    }
}

Alternative Installation Methods

Using Local Module

If you want to include the library as a local module:

Step 1: Clone the repository into your project:

cd YourProject
git clone https://github.com/samyak2403/SMailTM.git smailtm

Step 2: Add to settings.gradle.kts:

include(":app", ":smailtm")

Step 3: Add dependency in app/build.gradle.kts:

dependencies {
    implementation(project(":smailtm"))
}

Using Maven

Add to your pom.xml:

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

<dependency>
    <groupId>com.github.samyak2403</groupId>
    <artifactId>SMailTM</artifactId>
    <version>SMailTM-v1.0.1</version>
</dependency>

System Requirements

Before installing, ensure your project meets these requirements:

Requirement Minimum Version
Android SDK API 24 (Android 7.0)
Kotlin 1.9.0 or higher
Gradle 7.0 or higher
Java 11 or higher

Troubleshooting Installation

Issue: "Failed to resolve: com.github.samyak2403:SMailTM"

  • Solution: Make sure JitPack repository is added correctly
  • Verify internet connection
  • Try invalidating cache: File β†’ Invalidate Caches β†’ Restart

Issue: "Manifest merger failed"

  • Solution: Permissions are already added automatically by the library
  • If conflict occurs, add tools:replace="android:name" to your manifest

Issue: Build fails with "Duplicate class" error

  • Solution: Check for conflicting dependencies (OkHttp, Gson)
  • Use dependency resolution strategy if needed

πŸš€ Quick Start

Complete Step-by-Step Working Example

Step 1: Import Required Classes

import com.samyak.smailtm.util.SMailBuilder
import com.samyak.smailtm.util.Message
import com.samyak.smailtm.util.Response
import com.samyak.smailtm.util.Account
import com.samyak.smailtm.SMailTM
import com.samyak.smailtm.callbacks.MessageFetchedCallback
import com.samyak.smailtm.callbacks.EventListener
import javax.security.auth.login.LoginException
import kotlinx.coroutines.*
import androidx.lifecycle.lifecycleScope

Step 2: Create a Temporary Email Account

// In your Activity or Fragment
lifecycleScope.launch(Dispatchers.IO) {
    try {
        // Create account with random email
        val mailTM = SMailBuilder.createDefault("yourPassword123")
        mailTM.init()
        
        // Get account details
        val account = mailTM.getSelf()
        
        withContext(Dispatchers.Main) {
            println("βœ… Account created!")
            println("πŸ“§ Email: ${account.email}")
            println("πŸ†” ID: ${account.id}")
            Toast.makeText(this@MainActivity, "Email: ${account.email}", Toast.LENGTH_LONG).show()
        }
    } catch (e: LoginException) {
        withContext(Dispatchers.Main) {
            println("❌ Failed: ${e.message}")
        }
    }
}

Step 3: Fetch Messages

mailTM.asyncFetchMessages(object : MessageFetchedCallback {
    override fun onMessagesFetched(messages: List<Message>) {
        println("πŸ“¬ Received ${messages.size} messages")
        
        messages.forEach { message ->
            println("From: ${message.senderAddress}")
            println("Subject: ${message.subject}")
            println("Content: ${message.content}")
            println("Has Attachments: ${message.hasAttachments}")
        }
    }
    
    override fun onError(error: Response) {
        println("❌ Error: ${error.responseCode}")
    }
})

Step 4: Listen for Real-time Messages

mailTM.openEventListener(object : EventListener {
    override fun onReady() {
        println("βœ… Listening for new messages...")
    }
    
    override fun onMessageReceived(message: Message) {
        println("πŸ“§ New message from: ${message.senderAddress}")
        println("Subject: ${message.subject}")
        
        // Automatically mark as read
        message.asyncMarkAsRead()
    }
    
    override fun onMessageSeen(message: Message) {
        println("πŸ‘οΈ Message marked as seen")
    }
    
    override fun onMessageDelete(id: String) {
        println("πŸ—‘οΈ Message deleted: $id")
    }
    
    override fun onAccountUpdate(account: Account) {
        println("πŸ”„ Account updated")
    }
    
    override fun onAccountDelete(account: Account) {
        println("❌ Account deleted")
    }
    
    override fun onError(error: String) {
        println("⚠️ Error: $error")
    }
})

Step 5: Clean Up (Important!)

// In your Activity/Fragment lifecycle
override fun onDestroy() {
    super.onDestroy()
    mailTM?.closeMessageListener()  // Stop listening
}

Complete Working MainActivity Example

class MainActivity : AppCompatActivity() {
    private var mailTM: SMailTM? = null
    private lateinit var emailTextView: TextView
    private lateinit var messagesRecyclerView: RecyclerView
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        emailTextView = findViewById(R.id.emailTextView)
        messagesRecyclerView = findViewById(R.id.messagesRecyclerView)
        
        setupTemporaryEmail()
    }
    
    private fun setupTemporaryEmail() {
        lifecycleScope.launch(Dispatchers.IO) {
            try {
                // Create account
                mailTM = SMailBuilder.createDefault("password123")
                mailTM?.init()
                
                val account = mailTM?.getSelf()
                
                withContext(Dispatchers.Main) {
                    emailTextView.text = account?.email
                    Toast.makeText(
                        this@MainActivity,
                        "βœ… Email ready: ${account?.email}",
                        Toast.LENGTH_LONG
                    ).show()
                }
                
                // Start listening for messages
                mailTM?.openEventListener(object : EventListener {
                    override fun onReady() {
                        Log.d("SMailTM", "Ready to receive messages")
                    }
                    
                    override fun onMessageReceived(message: Message) {
                        runOnUiThread {
                            showNotification(message)
                            refreshMessages()
                        }
                    }
                    
                    override fun onError(error: String) {
                        Log.e("SMailTM", "Error: $error")
                    }
                    
                    // Implement other methods...
                    override fun onMessageSeen(message: Message) {}
                    override fun onMessageDelete(id: String) {}
                    override fun onAccountUpdate(account: Account) {}
                    override fun onAccountDelete(account: Account) {}
                })
                
            } catch (e: Exception) {
                withContext(Dispatchers.Main) {
                    Toast.makeText(
                        this@MainActivity,
                        "❌ Error: ${e.message}",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            }
        }
    }
    
    private fun refreshMessages() {
        mailTM?.asyncFetchMessages(object : MessageFetchedCallback {
            override fun onMessagesFetched(messages: List<Message>) {
                runOnUiThread {
                    // Update your RecyclerView adapter here
                    Log.d("SMailTM", "Fetched ${messages.size} messages")
                }
            }
            
            override fun onError(error: Response) {
                Log.e("SMailTM", "Error fetching messages: ${error.responseCode}")
            }
        })
    }
    
    private fun showNotification(message: Message) {
        Toast.makeText(
            this,
            "πŸ“§ New email from: ${message.senderAddress}",
            Toast.LENGTH_LONG
        ).show()
    }
    
    override fun onDestroy() {
        super.onDestroy()
        mailTM?.closeMessageListener()
    }
}

Basic Example (Simplified)

import com.samyak.smailtm.util.SMailBuilder
import com.samyak.smailtm.callbacks.MessageFetchedCallback
import javax.security.auth.login.LoginException

// Create a temporary email account
val mailTM = SMailBuilder.createDefault("password123")
mailTM.init()

// Get account info
val account = mailTM.getSelf()
println("Your temporary email: ${account.email}")

// Fetch messages
mailTM.fetchMessages(object : MessageFetchedCallback {
    override fun onMessagesFetched(messages: List<Message>) {
        messages.forEach { message ->
            println("From: ${message.senderAddress}")
            println("Subject: ${message.subject}")
        }
    }
    
    override fun onError(error: Response) {
        println("Error: ${error.responseCode}")
    }
})

πŸ“– Usage

Creating an Account

Create with Random Email

import com.samyak.SMailTM.util.SMailBuilder
import javax.security.auth.login.LoginException

try {
    // Create a random account
    val mailTM = SMailBuilder.createDefault("your_password")
    mailTM.init()
    
    val account = mailTM.getSelf()
    println("Account created: ${account.email}")
    println("Account ID: ${account.id}")
    println("Quota: ${account.quota} bytes")
} catch (e: LoginException) {
    println("Failed to create account: ${e.message}")
}

Create with Specific Email

try {
    val email = "myemail@example.com"
    val mailTM = SMailBuilder.createAndLogin(email, "password")
    
    println("Account created: ${mailTM.getSelf().email}")
} catch (e: LoginException) {
    println("Failed to create account: ${e.message}")
}

Login to Existing Account

Login with Email and Password

try {
    val mailTM = SMailBuilder.login("email@domain.com", "password")
    val account = mailTM.getSelf()
    
    println("Logged in as: ${account.email}")
    println("Used storage: ${account.used} bytes")
} catch (e: LoginException) {
    println("Login failed: ${e.message}")
}

Login with Token

try {
    val mailTM = SMailBuilder.loginWithToken("your_jwt_token")
    println("Logged in with token")
} catch (e: LoginException) {
    println("Token login failed: ${e.message}")
}

Fetching Messages

Fetch All Messages

import com.samyak.SMailTM.callbacks.MessageFetchedCallback
import com.samyak.SMailTM.util.Message
import com.samyak.SMailTM.util.Response

mailTM.fetchMessages(object : MessageFetchedCallback {
    override fun onMessagesFetched(messages: List<Message>) {
        messages.forEach { message ->
            println("From: ${message.senderAddress}")
            println("Subject: ${message.subject}")
            println("Content: ${message.content}")
            println("Seen: ${message.seen}")
            println("Has Attachments: ${message.hasAttachments}")
        }
    }
    
    override fun onError(error: Response) {
        println("Error: ${error.response}")
    }
})

Fetch Limited Messages

// Fetch only the latest 10 messages
mailTM.fetchMessages(10, object : MessageFetchedCallback {
    override fun onMessagesFetched(messages: List<Message>) {
        println("Fetched ${messages.size} messages")
    }
    
    override fun onError(error: Response) {
        println("Error: ${error.response}")
    }
})

Async Message Fetching

mailTM.asyncFetchMessages(object : MessageFetchedCallback {
    override fun onMessagesFetched(messages: List<Message>) {
        println("Messages fetched asynchronously")
    }
    
    override fun onError(error: Response) {
        println("Error: ${error.response}")
    }
})

Get Specific Message

val message = mailTM.getMessageById("message_id")
println("Subject: ${message.subject}")
println("From: ${message.senderName} <${message.senderAddress}>")

Real-time Event Listener

import com.samyak.SMailTM.callbacks.EventListener
import com.samyak.SMailTM.util.Account

mailTM.openEventListener(object : EventListener {
    override fun onReady() {
        println("Event listener is ready")
    }
    
    override fun onMessageReceived(message: Message) {
        println("πŸ“§ New message from: ${message.senderAddress}")
        println("Subject: ${message.subject}")
        
        // Auto-mark as read
        message.asyncMarkAsRead()
    }
    
    override fun onMessageSeen(message: Message) {
        println("πŸ‘οΈ Message marked as seen: ${message.id}")
    }
    
    override fun onMessageDelete(id: String) {
        println("πŸ—‘οΈ Message deleted: $id")
    }
    
    override fun onAccountUpdate(account: Account) {
        println("πŸ”„ Account updated")
    }
    
    override fun onAccountDelete(account: Account) {
        println("❌ Account deleted")
    }
    
    override fun onError(error: String) {
        println("⚠️ Error: $error")
    }
})

// Close listener when done
mailTM.closeMessageListener()

Custom Retry Interval

// Retry connection every 5 seconds on failure
mailTM.openEventListener(eventListener, retryInterval = 5000L)

Message Operations

Mark as Read

// Synchronous
val success = message.markAsRead()
println("Marked as read: $success")

// With callback
message.markAsRead { status ->
    println("Mark as read status: $status")
}

// Asynchronous
message.asyncMarkAsRead()

// Async with callback
message.asyncMarkAsRead { status ->
    println("Async mark as read: $status")
}

Delete Message

// Synchronous
val deleted = message.delete()
println("Message deleted: $deleted")

// With callback
message.delete { status ->
    println("Delete status: $status")
}

// Asynchronous
message.asyncDelete()

// Async with callback
message.asyncDelete { status ->
    println("Async delete: $status")
}

Get Message Details

// Get receivers
val receivers = message.getReceivers()
receivers.forEach { receiver ->
    println("To: ${receiver.address}")
}

// Get HTML content
val htmlContent = message.getRawHTML()
println("HTML: $htmlContent")

// Get raw JSON
val jsonData = message.getRawJson()
println("JSON: $jsonData")

// Get date/time
val createdDateTime = message.getCreatedDateTime()
println("Created: $createdDateTime")

Working with Attachments

val message = mailTM.getMessageById("message_id")

if (message.hasAttachments) {
    message.attachments.forEach { attachment ->
        println("Filename: ${attachment.filename}")
        println("Size: ${attachment.size} bytes")
        println("Type: ${attachment.contentType}")
        println("ID: ${attachment.id}")
        
        // Save to current directory
        attachment.save()
        
        // Save with custom filename
        attachment.save("custom_name.pdf")
        
        // Save with callback
        attachment.save("file.pdf") { status ->
            if (status) {
                println("βœ… Downloaded: ${attachment.filename}")
            } else {
                println("❌ Download failed")
            }
        }
        
        // Save to custom path
        attachment.save("/path/to/directory", "filename.pdf") { status ->
            println("Save status: $status")
        }
    }
}

Account Management

Get Account Information

val account = mailTM.getSelf()
println("Email: ${account.email}")
println("ID: ${account.id}")
println("Quota: ${account.quota} bytes")
println("Used: ${account.used} bytes")
println("Is Disabled: ${account.isDisabled}")
println("Is Deleted: ${account.isDeleted}")
println("Created At: ${account.createdAt}")
println("Updated At: ${account.updatedAt}")

Delete Account

// Synchronous
val deleted = mailTM.delete()
println("Account deleted: $deleted")

// With callback
mailTM.delete { status ->
    println("Delete status: $status")
}

// Asynchronous
mailTM.asyncDelete()

// Async with callback
mailTM.asyncDelete { status ->
    println("Async delete: $status")
}

Get Total Messages

val totalMessages = mailTM.getTotalMessages()
println("Total messages: $totalMessages")

Domain Management

import com.samyak.SMailTM.util.Domains

// Fetch all available domains
val domains = Domains.fetchDomains()
domains.forEach { domain ->
    println("Domain: ${domain.domainName}")
    println("Active: ${domain.isActive}")
    println("Private: ${domain.isPrivate}")
}

// Get a random domain
val randomDomain = Domains.getRandomDomain()
println("Random domain: ${randomDomain.domainName}")

// Fetch domain by ID
val domain = Domains.fetchDomainById("domain_id")
println("Domain: ${domain.domainName}")

// Create account with specific domain
val email = "myname@${randomDomain.domainName}"
val mailTM = SMailBuilder.createAndLogin(email, "password")

πŸ”§ Advanced Usage

Using with Kotlin Coroutines

import kotlinx.coroutines.*

lifecycleScope.launch {
    try {
        // Create account on IO thread
        val mail = withContext(Dispatchers.IO) {
            SMailBuilder.createDefault("password")
        }
        mail.init()
        
        // Get account info
        val account = withContext(Dispatchers.IO) {
            mail.getSelf()
        }
        
        println("Email: ${account.email}")
        
        // Fetch messages
        withContext(Dispatchers.IO) {
            mail.fetchMessages(object : MessageFetchedCallback {
                override fun onMessagesFetched(messages: List<Message>) {
                    // Update UI on Main thread
                    launch(Dispatchers.Main) {
                        println("Received ${messages.size} messages")
                    }
                }
                
                override fun onError(error: Response) {
                    println("Error: ${error.responseCode}")
                }
            })
        }
    } catch (e: Exception) {
        println("Error: ${e.message}")
    }
}

Persistent Sessions with Tokens

// First login - save token
val mailTM = SMailBuilder.login("email@domain.com", "password")
val account = mailTM.getSelf()
val token = account.token

// Save token to SharedPreferences
val prefs = context.getSharedPreferences("mail_prefs", Context.MODE_PRIVATE)
prefs.edit().putString("auth_token", token).apply()

// Later - login with saved token
val savedToken = prefs.getString("auth_token", null)
if (savedToken != null) {
    val mailTM = SMailBuilder.loginWithToken(savedToken)
    println("Logged in with saved token")
}

Custom Domain Selection

import com.samyak.SMailTM.util.Domains

// Get available domains
val domains = Domains.fetchDomains()

// Filter active domains
val activeDomains = domains.filter { it.isActive }

// Select preferred domain
val preferredDomain = activeDomains.firstOrNull { 
    it.domainName.contains("mail.tm") 
} ?: activeDomains.first()

// Create account with selected domain
val email = "myusername@${preferredDomain.domainName}"
val mailTM = SMailBuilder.createAndLogin(email, "password")

Handling Multiple Accounts

class EmailManager {
    private val accounts = mutableMapOf<String, SMailTM>()
    
    fun addAccount(email: String, password: String) {
        try {
            val mailTM = SMailBuilder.login(email, password)
            accounts[email] = mailTM
            println("Added account: $email")
        } catch (e: LoginException) {
            println("Failed to add account: ${e.message}")
        }
    }
    
    fun getAccount(email: String): SMailTM? {
        return accounts[email]
    }
    
    fun removeAccount(email: String) {
        accounts[email]?.delete()
        accounts.remove(email)
    }
    
    fun getAllAccounts(): List<String> {
        return accounts.keys.toList()
    }
}

πŸ“š API Reference

SMailBuilder

Factory class for creating and managing SMailTM instances.

Method Parameters Returns Description
login() email: String, password: String SMailTM Login to existing account
create() email: String, password: String Boolean Create new account
createAndLogin() email: String, password: String SMailTM Create and login in one step
createDefault() password: String SMailTM Create account with random email
loginWithToken() token: String SMailTM Login using JWT token

SMailTM

Main class for interacting with Mail.tm API.

Account Methods

Method Returns Description
init() void Initialize the account
getSelf() Account Get current account info
delete() Boolean Delete account (sync)
delete(callback) void Delete account with callback
asyncDelete() void Delete account (async)
asyncDelete(callback) void Delete account async with callback
getAccountById(id) Account Get account by ID

Message Methods

Method Returns Description
getTotalMessages() Int Get total message count
getMessageById(id) Message Get specific message
fetchMessages(callback) void Fetch all messages
fetchMessages(limit, callback) void Fetch limited messages
asyncFetchMessages(callback) void Fetch messages async
asyncFetchMessages(limit, callback) void Fetch limited messages async

Event Listener Methods

Method Returns Description
openEventListener(listener) void Start SSE listener
openEventListener(listener, retry) void Start with custom retry interval
closeMessageListener() void Stop SSE listener

Message

Represents an email message.

Properties

Property Type Description
id String Message ID
msgid String Message identifier
from Sender Sender information
to Any? Recipient(s)
subject String Email subject
text String Plain text content
html List HTML content
seen Boolean Read status
flagged Boolean Flagged status
isDeleted Boolean Deletion status
hasAttachments Boolean Has attachments
attachments List Attachment list
size Long Message size in bytes
createdAt String Creation timestamp
updatedAt String Update timestamp
senderAddress String Sender email (computed)
senderName String Sender name (computed)
content String Message content (computed)

Methods

Method Returns Description
delete() Boolean Delete message (sync)
delete(callback) void Delete with callback
asyncDelete() void Delete async
asyncDelete(callback) void Delete async with callback
markAsRead() Boolean Mark as read (sync)
markAsRead(callback) void Mark as read with callback
asyncMarkAsRead() void Mark as read async
asyncMarkAsRead(callback) void Mark as read async with callback
getReceivers() List Get recipient list
getRawHTML() String Get raw HTML
getRawJson() String Get raw JSON
getCreatedDateTime() ZonedDateTime Get creation date
getUpdatedDateTime() ZonedDateTime Get update date

Attachment

Represents an email attachment.

Property Type Description
id String Attachment ID
filename String File name
contentType String MIME type
size Long File size in bytes
downloadUrl String Download URL
Method Returns Description
saveSync() Boolean Save to current directory
saveSync(filename) Boolean Save with custom name
saveSync(path, filename) Boolean Save to custom path
save() void Save async
save(callback) void Save with callback
save(filename) void Save with custom name async
save(filename, callback) void Save with callback
save(path, filename, callback) void Save to custom path with callback

Domains

Utility class for domain management.

Method Returns Description
fetchDomains() List Get all available domains
getRandomDomain() Domain Get random domain
fetchDomainById(id) Domain Get specific domain

Callbacks

EventListener

interface EventListener {
    fun onReady()
    fun onMessageReceived(message: Message)
    fun onMessageSeen(message: Message)
    fun onMessageDelete(id: String)
    fun onAccountUpdate(account: Account)
    fun onAccountDelete(account: Account)
    fun onError(error: String)
}

MessageFetchedCallback

interface MessageFetchedCallback {
    fun onMessagesFetched(messages: List<Message>)
    fun onError(error: Response)
}

WorkCallback

interface WorkCallback {
    fun workStatus(status: Boolean)
}

πŸ› Error Handling

Exception Handling

import javax.security.auth.login.LoginException

try {
    val mailTM = SMailBuilder.login("email@domain.com", "password")
} catch (e: LoginException) {
    when {
        e.message?.contains("401") == true -> {
            println("❌ Invalid credentials")
        }
        e.message?.contains("404") == true -> {
            println("❌ Account not found")
        }
        e.message?.contains("429") == true -> {
            println("⚠️ Too many requests - rate limited")
        }
        else -> {
            println("❌ Login failed: ${e.message}")
        }
    }
}

Response Error Handling

mailTM.fetchMessages(object : MessageFetchedCallback {
    override fun onMessagesFetched(messages: List<Message>) {
        println("βœ… Fetched ${messages.size} messages")
    }
    
    override fun onError(error: Response) {
        when (error.responseCode) {
            401 -> println("❌ Unauthorized - token expired")
            404 -> println("❌ Not found")
            429 -> println("⚠️ Rate limit exceeded")
            500 -> println("❌ Server error")
            503 -> println("⚠️ Service unavailable")
            else -> println("❌ Error ${error.responseCode}: ${error.response}")
        }
    }
})

Network Error Handling

try {
    mailTM.fetchMessages(callback)
} catch (e: java.net.UnknownHostException) {
    println("❌ No internet connection")
} catch (e: java.net.SocketTimeoutException) {
    println("⚠️ Connection timeout")
} catch (e: Exception) {
    println("❌ Unexpected error: ${e.message}")
}

πŸ“ Best Practices

1. Always Close Event Listeners

class MainActivity : AppCompatActivity() {
    private var mailTM: SMailTM? = null
    
    override fun onDestroy() {
        super.onDestroy()
        mailTM?.closeMessageListener()
    }
}

2. Use Async Methods for Better Performance

// βœ… Good - Non-blocking
mailTM.asyncFetchMessages(callback)
message.asyncMarkAsRead()
message.asyncDelete()

// ❌ Avoid - Blocking
mailTM.fetchMessages(callback) // Blocks current thread
message.markAsRead() // Blocks current thread

3. Store Tokens for Persistent Sessions

// Save token after login
val token = mailTM.getSelf().token
sharedPreferences.edit().putString("auth_token", token).apply()

// Reuse token on app restart
val savedToken = sharedPreferences.getString("auth_token", null)
if (savedToken != null) {
    mailTM = SMailBuilder.loginWithToken(savedToken)
}

4. Handle Network Operations on Background Thread

lifecycleScope.launch(Dispatchers.IO) {
    try {
        val mail = SMailBuilder.createDefault("password")
        mail.init()
        
        withContext(Dispatchers.Main) {
            // Update UI
        }
    } catch (e: Exception) {
        withContext(Dispatchers.Main) {
            // Show error
        }
    }
}

5. Implement Proper Error Handling

mailTM.fetchMessages(object : MessageFetchedCallback {
    override fun onMessagesFetched(messages: List<Message>) {
        // Success
    }
    
    override fun onError(error: Response) {
        // Always handle errors
        when (error.responseCode) {
            401 -> refreshToken()
            429 -> scheduleRetry()
            else -> showError(error.response)
        }
    }
})

6. Clean Up Resources

// Delete account when no longer needed
mailTM.asyncDelete { success ->
    if (success) {
        println("βœ… Account cleaned up")
    }
}

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

How to Contribute

  1. Fork the repository

    git clone https://github.com/samyak2403/SMailTM.git
  2. Create your feature branch

    git checkout -b feature/AmazingFeature
  3. Commit your changes

    git commit -m 'Add some AmazingFeature'
  4. Push to the branch

    git push origin feature/AmazingFeature
  5. Open a Pull Request

Development Setup

# Clone the repository
git clone https://github.com/samyak2403/SMailTM.git
cd SMailTM

# Open in Android Studio
# Build the project
./gradlew build

# Run tests
./gradlew test

Code Style

  • Follow Kotlin coding conventions
  • Use meaningful variable and function names
  • Add comments for complex logic
  • Write unit tests for new features

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

MIT License

Copyright (c) 2024 Samyak

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

πŸ™ Credits

This library is a Kotlin conversion of JMailTM created by shivzee.

Original Java Library

Mail.tm Service

Special Thanks

  • JMailTM Contributors - For the original Java implementation
  • Mail.tm Team - For providing the temporary email service
  • Kotlin Community - For the amazing language and ecosystem

πŸ“§ Support

For issues, questions, or contributions, please visit:

πŸ”— Links

πŸ“Š Stats

  • Language: Kotlin 100%
  • Min SDK: 24 (Android 7.0)
  • License: MIT
  • Status: Active Development

πŸ—ΊοΈ Roadmap

  • Add support for custom SMTP servers
  • Implement message filtering and search
  • Add support for message forwarding
  • Implement email templates
  • Add support for scheduled messages
  • Improve error handling and retry logic
  • Add comprehensive unit tests
  • Publish to Maven Central
  • Add support for multiple languages
  • Implement message encryption

Made with ❀️ in Kotlin

Star ⭐ this repository if you find it helpful!

⭐ Star this repository if you find it helpful!

πŸ› Found a bug? Report it here

πŸ’‘ Have a feature request? Let us know

Morty Proxy This is a proxified and sanitized view of the page, visit original site.