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.
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.
- 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
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
- Apps Using SMailTM
- Features
- Installation
- Quick Start
- Usage
- API Reference
- Advanced Usage
- Best Practices
- Contributing
- License
- Credits
- π§ 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
Follow these steps to integrate SMailTM into your Android project:
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
}
}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'
}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>Click "Sync Now" in Android Studio or run:
./gradlew buildCreate 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}")
}
}
}
}
}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 smailtmStep 2: Add to settings.gradle.kts:
include(":app", ":smailtm")Step 3: Add dependency in app/build.gradle.kts:
dependencies {
implementation(project(":smailtm"))
}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>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 |
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
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// 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}")
}
}
}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}")
}
})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")
}
})// In your Activity/Fragment lifecycle
override fun onDestroy() {
super.onDestroy()
mailTM?.closeMessageListener() // Stop listening
}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()
}
}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}")
}
})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}")
}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}")
}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}")
}try {
val mailTM = SMailBuilder.loginWithToken("your_jwt_token")
println("Logged in with token")
} catch (e: LoginException) {
println("Token login failed: ${e.message}")
}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 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}")
}
})mailTM.asyncFetchMessages(object : MessageFetchedCallback {
override fun onMessagesFetched(messages: List<Message>) {
println("Messages fetched asynchronously")
}
override fun onError(error: Response) {
println("Error: ${error.response}")
}
})val message = mailTM.getMessageById("message_id")
println("Subject: ${message.subject}")
println("From: ${message.senderName} <${message.senderAddress}>")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()// Retry connection every 5 seconds on failure
mailTM.openEventListener(eventListener, retryInterval = 5000L)// 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")
}// 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 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")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")
}
}
}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}")// 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")
}val totalMessages = mailTM.getTotalMessages()
println("Total messages: $totalMessages")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")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}")
}
}// 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")
}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")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()
}
}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 |
Main class for interacting with Mail.tm API.
| 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 |
| 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 |
| Method | Returns | Description |
|---|---|---|
openEventListener(listener) |
void | Start SSE listener |
openEventListener(listener, retry) |
void | Start with custom retry interval |
closeMessageListener() |
void | Stop SSE listener |
Represents an email message.
| 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) |
| 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 |
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 |
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 |
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)
}interface MessageFetchedCallback {
fun onMessagesFetched(messages: List<Message>)
fun onError(error: Response)
}interface WorkCallback {
fun workStatus(status: Boolean)
}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}")
}
}
}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}")
}
}
})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}")
}class MainActivity : AppCompatActivity() {
private var mailTM: SMailTM? = null
override fun onDestroy() {
super.onDestroy()
mailTM?.closeMessageListener()
}
}// β
Good - Non-blocking
mailTM.asyncFetchMessages(callback)
message.asyncMarkAsRead()
message.asyncDelete()
// β Avoid - Blocking
mailTM.fetchMessages(callback) // Blocks current thread
message.markAsRead() // Blocks current thread// 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)
}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
}
}
}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)
}
}
})// Delete account when no longer needed
mailTM.asyncDelete { success ->
if (success) {
println("β
Account cleaned up")
}
}Contributions are welcome! Please feel free to submit a Pull Request.
-
Fork the repository
git clone https://github.com/samyak2403/SMailTM.git
-
Create your feature branch
git checkout -b feature/AmazingFeature
-
Commit your changes
git commit -m 'Add some AmazingFeature' -
Push to the branch
git push origin feature/AmazingFeature
-
Open a Pull Request
# 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- Follow Kotlin coding conventions
- Use meaningful variable and function names
- Add comments for complex logic
- Write unit tests for new features
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.
This library is a Kotlin conversion of JMailTM created by shivzee.
- Repository: https://github.com/shivam1608/JMailTM
- Author: shivzee
- License: MIT
- Website: https://mail.tm
- API Documentation: https://docs.mail.tm
- Service Provider: Mail.tm Team
- JMailTM Contributors - For the original Java implementation
- Mail.tm Team - For providing the temporary email service
- Kotlin Community - For the amazing language and ecosystem
For issues, questions, or contributions, please visit:
- GitHub Issues: Report a bug
- GitHub Discussions: Ask a question
- Email: arrowwould@gmail.com
- Mail.tm API Documentation: https://docs.mail.tm/
- JMailTM Original Library: https://github.com/shivam1608/JMailTM
- Kotlin Documentation: https://kotlinlang.org/docs/home.html
- Android Developers: https://developer.android.com/
- Language: Kotlin 100%
- Min SDK: 24 (Android 7.0)
- License: MIT
- Status: Active Development
- 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