javascript
Tools
tempemail
Email Sementara
#scrape#emailtemp#tempemail#tools
Base URL
https://mail.tm
javascript
| 1 | /** |
| 2 | * email.js |
| 3 | * |
| 4 | * author : zavedyaaid |
| 5 | * ch author : https://whatsapp.com/channel/0029VbC6Qmr4dTnGB19pok0Y |
| 6 | * |
| 7 | * Command: |
| 8 | * node email.js --new [nama] -> bikin email baru |
| 9 | * node email.js --get <email> -> list ringkas semua pesan + ID & setengah isi |
| 10 | * node email.js --read <email> <id> -> baca isi lengkap pesan tertentu (beserta link) |
| 11 | * node email.js -> liat email yang lagi aktif |
| 12 | */ |
| 13 | |
| 14 | const fs = require('fs'); |
| 15 | const path = require('path'); |
| 16 | const crypto = require('crypto'); |
| 17 | |
| 18 | const STATE_FILE = path.join(__dirname, '.tempmail.json'); |
| 19 | const API = 'https://api.mail.tm'; |
| 20 | |
| 21 | function loadState() { |
| 22 | if (fs.existsSync(STATE_FILE)) { |
| 23 | return JSON.parse(fs.readFileSync(STATE_FILE, 'utf8')); |
| 24 | } |
| 25 | return null; |
| 26 | } |
| 27 | |
| 28 | function saveState(state) { |
| 29 | fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2)); |
| 30 | } |
| 31 | |
| 32 | // Fungsi request dengan retry otomatis untuk mengatasi 503 / gangguan jaringan sesaat |
| 33 | async function apiRequest(method, endpoint, { body, token } = {}, retries = 3) { |
| 34 | const headers = { |
| 35 | 'Content-Type': 'application/json', |
| 36 | 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' |
| 37 | }; |
| 38 | if (token) headers.Authorization = `Bearer ${token}`; |
| 39 | |
| 40 | for (let i = 0; i < retries; i++) { |
| 41 | try { |
| 42 | const res = await fetch(`${API}${endpoint}`, { |
| 43 | method, |
| 44 | headers, |
| 45 | body: body ? JSON.stringify(body) : undefined, |
| 46 | }); |
| 47 | |
| 48 | const text = await res.text(); |
| 49 | let json; |
| 50 | try { |
| 51 | json = text ? JSON.parse(text) : {}; |
| 52 | } catch { |
| 53 | json = { raw: text }; |
| 54 | } |
| 55 | |
| 56 | if (!res.ok) { |
| 57 | const msg = json.message || json['hydra:description'] || text || res.statusText; |
| 58 | // Kalau error 503 atau 5xx, coba ulangi lagi beberapa detik kemudian |
| 59 | if (res.status >= 500 && i < retries - 1) { |
| 60 | await new Promise(r => setTimeout(r, 2000)); |
| 61 | continue; |
| 62 | } |
| 63 | throw new Error(`API error: ${res.status} — ${msg}`); |
| 64 | } |
| 65 | return json; |
| 66 | } catch (err) { |
| 67 | if (i === retries - 1) throw err; |
| 68 | await new Promise(r => setTimeout(r, 2000)); |
| 69 | } |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | function randomString(len) { |
| 74 | return crypto.randomBytes(len).toString('hex').slice(0, len); |
| 75 | } |
| 76 | |
| 77 | function parseContent(msgObj) { |
| 78 | if (msgObj.text && msgObj.text.trim()) { |
| 79 | return msgObj.text; |
| 80 | } |
| 81 | |
| 82 | if (msgObj.html && msgObj.html.length > 0) { |
| 83 | const htmlCombined = msgObj.html.join('\n'); |
| 84 | let cleanText = htmlCombined |
| 85 | .replace(/<a\s+(?:[^>]*?\s+)?href="([^"]*)"[^>]*>(.*?)<\/a>/gi, '$2 ($1)') |
| 86 | .replace(/<[^>]+>/g, '') |
| 87 | .replace(/ /g, ' ') |
| 88 | .trim(); |
| 89 | |
| 90 | return cleanText; |
| 91 | } |
| 92 | |
| 93 | return '(tidak ada isi teks)'; |
| 94 | } |
| 95 | |
| 96 | async function createNewEmail(customName) { |
| 97 | const domains = await apiRequest('GET', '/domains'); |
| 98 | if (!domains['hydra:member'] || domains['hydra:member'].length === 0) { |
| 99 | throw new Error('Tidak ada domain mail.tm yang tersedia saat ini.'); |
| 100 | } |
| 101 | const domain = domains['hydra:member'][0].domain; |
| 102 | |
| 103 | const login = customName |
| 104 | ? `${customName.toLowerCase().replace(/[^a-z0-9]/g, '')}${randomString(3)}` |
| 105 | : `zvd${randomString(8)}`; |
| 106 | const password = randomString(16); |
| 107 | const address = `${login}@${domain}`; |
| 108 | |
| 109 | const accRes = await apiRequest('POST', '/accounts', { body: { address, password } }); |
| 110 | const tokenRes = await apiRequest('POST', '/token', { body: { address, password } }); |
| 111 | |
| 112 | const state = { |
| 113 | id: accRes.id, |
| 114 | address, |
| 115 | password, |
| 116 | token: tokenRes.token, |
| 117 | createdAt: new Date().toISOString(), |
| 118 | }; |
| 119 | saveState(state); |
| 120 | console.log(`✅ Email sementara dibuat:`); |
| 121 | console.log(`- ID Akun : ${state.id}`); |
| 122 | console.log(`- Alamat : ${state.address}`); |
| 123 | return state; |
| 124 | } |
| 125 | |
| 126 | function requireState(targetEmail) { |
| 127 | if (!targetEmail) { |
| 128 | console.log('⚠️ Format salah! Wajib sertakan email.'); |
| 129 | process.exit(1); |
| 130 | } |
| 131 | |
| 132 | const state = loadState(); |
| 133 | if (!state) { |
| 134 | console.log('⚠️ Belum ada data email tersimpan di lokal.'); |
| 135 | process.exit(1); |
| 136 | } |
| 137 | |
| 138 | if (state.address.toLowerCase() !== targetEmail.toLowerCase()) { |
| 139 | console.log(`⚠️ Email "${targetEmail}" tidak cocok atau tidak aktif di state lokal saat ini.`); |
| 140 | console.log(`ℹ️ Email aktif: ${state.address}`); |
| 141 | process.exit(1); |
| 142 | } |
| 143 | |
| 144 | return state; |
| 145 | } |
| 146 | |
| 147 | async function refreshTokenIfNeeded(state) { |
| 148 | try { |
| 149 | await apiRequest('GET', '/me', { token: state.token }); |
| 150 | return state; |
| 151 | } catch { |
| 152 | const tokenRes = await apiRequest('POST', '/token', { |
| 153 | body: { address: state.address, password: state.password }, |
| 154 | }); |
| 155 | state.token = tokenRes.token; |
| 156 | saveState(state); |
| 157 | return state; |
| 158 | } |
| 159 | } |
| 160 | |
| 161 | async function getInboxList(targetEmail) { |
| 162 | let state = requireState(targetEmail); |
| 163 | state = await refreshTokenIfNeeded(state); |
| 164 | |
| 165 | const listRes = await apiRequest('GET', '/messages', { token: state.token }); |
| 166 | const messages = listRes['hydra:member'] || []; |
| 167 | |
| 168 | console.log(`📬 Inbox untuk ${state.address}`); |
| 169 | |
| 170 | if (messages.length === 0) { |
| 171 | console.log(' (kosong, belum ada pesan masuk)'); |
| 172 | return; |
| 173 | } |
| 174 | |
| 175 | messages.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)); |
| 176 | |
| 177 | for (const m of messages) { |
| 178 | const snippet = m.intro || (m.text ? m.text.slice(0, 100) : '(tanpa teks preview)'); |
| 179 | console.log('\n──────────────────────────────'); |
| 180 | console.log(`ID Pesan : ${m.id}`); |
| 181 | console.log(`Dari : ${m.from.address}`); |
| 182 | console.log(`Subjek : ${m.subject}`); |
| 183 | console.log(`Waktu : ${m.createdAt}`); |
| 184 | console.log(`Isi : ${snippet.trim()}...`); |
| 185 | console.log('──────────────────────────────'); |
| 186 | } |
| 187 | console.log(`\n💡 Tips: Untuk baca isi lengkap beserta link, ketik:`); |
| 188 | console.log(` node email.js --read ${state.address} <ID_PESAN>`); |
| 189 | } |
| 190 | |
| 191 | async function readMessageDetail(targetEmail, messageId) { |
| 192 | let state = requireState(targetEmail); |
| 193 | if (!messageId) { |
| 194 | console.log('⚠️ Wajib sertakan ID pesan! Contoh: node email.js --read <email> <id>'); |
| 195 | process.exit(1); |
| 196 | } |
| 197 | |
| 198 | state = await refreshTokenIfNeeded(state); |
| 199 | |
| 200 | try { |
| 201 | const full = await apiRequest('GET', `/messages/${messageId}`, { token: state.token }); |
| 202 | const contentParsed = parseContent(full); |
| 203 | |
| 204 | console.log('\n========================================'); |
| 205 | console.log(`📩 DETAIL PESAN`); |
| 206 | console.log('========================================'); |
| 207 | console.log(`ID : ${full.id}`); |
| 208 | console.log(`Dari : ${full.from.address}`); |
| 209 | console.log(`Subjek : ${full.subject}`); |
| 210 | console.log(`Waktu : ${full.createdAt}`); |
| 211 | console.log('----------------------------------------'); |
| 212 | console.log(contentParsed); |
| 213 | console.log('========================================'); |
| 214 | } catch (err) { |
| 215 | console.error(`❌ Gagal mengambil pesan dengan ID "${messageId}":`, err.message); |
| 216 | } |
| 217 | } |
| 218 | |
| 219 | function printHelp() { |
| 220 | console.log(` |
| 221 | email.js — email sementara dari terminal (pakai mail.tm) |
| 222 | |
| 223 | node email.js --new [nama] bikin email baru |
| 224 | node email.js --get <email> list ringkas semua pesan + ID & setengah isi |
| 225 | node email.js --read <email> <id> baca isi lengkap pesan tertentu (beserta link) |
| 226 | node email.js tampilkan email yang lagi aktif |
| 227 | `); |
| 228 | } |
| 229 | |
| 230 | async function main() { |
| 231 | const args = process.argv.slice(2); |
| 232 | let cmd = args[0]; |
| 233 | let targetParam = args[1]; |
| 234 | let extraParam = args[2]; |
| 235 | |
| 236 | if (cmd && cmd.includes('@')) { |
| 237 | targetParam = cmd; |
| 238 | cmd = args[1]; |
| 239 | extraParam = args[2]; |
| 240 | } |
| 241 | |
| 242 | try { |
| 243 | if (!cmd) { |
| 244 | const state = loadState(); |
| 245 | if (!state) { |
| 246 | console.log('⚠️ Belum ada email aktif. Jalankan: node email.js --new'); |
| 247 | } else { |
| 248 | console.log(`📧 Email aktif: ${state.address}`); |
| 249 | } |
| 250 | return; |
| 251 | } |
| 252 | |
| 253 | switch (cmd) { |
| 254 | case '--new': |
| 255 | await createNewEmail(targetParam); |
| 256 | break; |
| 257 | case '--get': |
| 258 | await getInboxList(targetParam); |
| 259 | break; |
| 260 | case '--read': |
| 261 | await readMessageDetail(targetParam, extraParam); |
| 262 | break; |
| 263 | case '--help': |
| 264 | case '-h': |
| 265 | printHelp(); |
| 266 | break; |
| 267 | default: |
| 268 | console.log(`⚠️ Command "${cmd}" nggak dikenal.`); |
| 269 | printHelp(); |
| 270 | } |
| 271 | } catch (err) { |
| 272 | console.error('❌ Error:', err.message); |
| 273 | process.exit(1); |
| 274 | } |
| 275 | } |
| 276 | |
| 277 | main(); |
/**
* email.js
*
* author : zavedyaaid
* ch author : https://whatsapp.com/channel/0029VbC6Qmr4dTnGB19pok0Y
*
* Command:
* node email.js --new [nama] -> bikin email baru
* node email.js --get <email> -> list ringkas semua pesan + ID & setengah isi
* node email.js --read <email> <id> -> baca isi lengkap pesan tertentu (beserta link)
* node email.js -> liat email yang lagi aktif
*/
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const STATE_FILE = path.join(__dirname, '.tempmail.json');
const API = 'https://api.mail.tm';
function loadState() {
if (fs.existsSync(STATE_FILE)) {
return JSON.parse(fs.readFileSync(STATE_FILE, 'utf8'));
}
return null;
}
function saveState(state) {
fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
}
// Fungsi request dengan retry otomatis untuk mengatasi 503 / gangguan jaringan sesaat
async function apiRequest(method, endpoint, { body, token } = {}, retries = 3) {
const headers = {
'Content-Type': 'application/json',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
};
if (token) headers.Authorization = `Bearer ${token}`;
for (let i = 0; i < retries; i++) {
try {
const res = await fetch(`${API}${endpoint}`, {
method,
headers,
body: body ? JSON.stringify(body) : undefined,
});
const text = await res.text();
let json;
try {
json = text ? JSON.parse(text) : {};
} catch {
json = { raw: text };
}
if (!res.ok) {
const msg = json.message || json['hydra:description'] || text || res.statusText;
// Kalau error 503 atau 5xx, coba ulangi lagi beberapa detik kemudian
if (res.status >= 500 && i < retries - 1) {
await new Promise(r => setTimeout(r, 2000));
continue;
}
throw new Error(`API error: ${res.status} — ${msg}`);
}
return json;
} catch (err) {
if (i === retries - 1) throw err;
await new Promise(r => setTimeout(r, 2000));
}
}
}
function randomString(len) {
return crypto.randomBytes(len).toString('hex').slice(0, len);
}
function parseContent(msgObj) {
if (msgObj.text && msgObj.text.trim()) {
return msgObj.text;
}
if (msgObj.html && msgObj.html.length > 0) {
const htmlCombined = msgObj.html.join('\n');
let cleanText = htmlCombined
.replace(/<a\s+(?:[^>]*?\s+)?href="([^"]*)"[^>]*>(.*?)<\/a>/gi, '$2 ($1)')
.replace(/<[^>]+>/g, '')
.replace(/ /g, ' ')
.trim();
return cleanText;
}
return '(tidak ada isi teks)';
}
async function createNewEmail(customName) {
const domains = await apiRequest('GET', '/domains');
if (!domains['hydra:member'] || domains['hydra:member'].length === 0) {
throw new Error('Tidak ada domain mail.tm yang tersedia saat ini.');
}
const domain = domains['hydra:member'][0].domain;
const login = customName
? `${customName.toLowerCase().replace(/[^a-z0-9]/g, '')}${randomString(3)}`
: `zvd${randomString(8)}`;
const password = randomString(16);
const address = `${login}@${domain}`;
const accRes = await apiRequest('POST', '/accounts', { body: { address, password } });
const tokenRes = await apiRequest('POST', '/token', { body: { address, password } });
const state = {
id: accRes.id,
address,
password,
token: tokenRes.token,
createdAt: new Date().toISOString(),
};
saveState(state);
console.log(`✅ Email sementara dibuat:`);
console.log(`- ID Akun : ${state.id}`);
console.log(`- Alamat : ${state.address}`);
return state;
}
function requireState(targetEmail) {
if (!targetEmail) {
console.log('⚠️ Format salah! Wajib sertakan email.');
process.exit(1);
}
const state = loadState();
if (!state) {
console.log('⚠️ Belum ada data email tersimpan di lokal.');
process.exit(1);
}
if (state.address.toLowerCase() !== targetEmail.toLowerCase()) {
console.log(`⚠️ Email "${targetEmail}" tidak cocok atau tidak aktif di state lokal saat ini.`);
console.log(`ℹ️ Email aktif: ${state.address}`);
process.exit(1);
}
return state;
}
async function refreshTokenIfNeeded(state) {
try {
await apiRequest('GET', '/me', { token: state.token });
return state;
} catch {
const tokenRes = await apiRequest('POST', '/token', {
body: { address: state.address, password: state.password },
});
state.token = tokenRes.token;
saveState(state);
return state;
}
}
async function getInboxList(targetEmail) {
let state = requireState(targetEmail);
state = await refreshTokenIfNeeded(state);
const listRes = await apiRequest('GET', '/messages', { token: state.token });
const messages = listRes['hydra:member'] || [];
console.log(`📬 Inbox untuk ${state.address}`);
if (messages.length === 0) {
console.log(' (kosong, belum ada pesan masuk)');
return;
}
messages.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt));
for (const m of messages) {
const snippet = m.intro || (m.text ? m.text.slice(0, 100) : '(tanpa teks preview)');
console.log('\n──────────────────────────────');
console.log(`ID Pesan : ${m.id}`);
console.log(`Dari : ${m.from.address}`);
console.log(`Subjek : ${m.subject}`);
console.log(`Waktu : ${m.createdAt}`);
console.log(`Isi : ${snippet.trim()}...`);
console.log('──────────────────────────────');
}
console.log(`\n💡 Tips: Untuk baca isi lengkap beserta link, ketik:`);
console.log(` node email.js --read ${state.address} <ID_PESAN>`);
}
async function readMessageDetail(targetEmail, messageId) {
let state = requireState(targetEmail);
if (!messageId) {
console.log('⚠️ Wajib sertakan ID pesan! Contoh: node email.js --read <email> <id>');
process.exit(1);
}
state = await refreshTokenIfNeeded(state);
try {
const full = await apiRequest('GET', `/messages/${messageId}`, { token: state.token });
const contentParsed = parseContent(full);
console.log('\n========================================');
console.log(`📩 DETAIL PESAN`);
console.log('========================================');
console.log(`ID : ${full.id}`);
console.log(`Dari : ${full.from.address}`);
console.log(`Subjek : ${full.subject}`);
console.log(`Waktu : ${full.createdAt}`);
console.log('----------------------------------------');
console.log(contentParsed);
console.log('========================================');
} catch (err) {
console.error(`❌ Gagal mengambil pesan dengan ID "${messageId}":`, err.message);
}
}
function printHelp() {
console.log(`
email.js — email sementara dari terminal (pakai mail.tm)
node email.js --new [nama] bikin email baru
node email.js --get <email> list ringkas semua pesan + ID & setengah isi
node email.js --read <email> <id> baca isi lengkap pesan tertentu (beserta link)
node email.js tampilkan email yang lagi aktif
`);
}
async function main() {
const args = process.argv.slice(2);
let cmd = args[0];
let targetParam = args[1];
let extraParam = args[2];
if (cmd && cmd.includes('@')) {
targetParam = cmd;
cmd = args[1];
extraParam = args[2];
}
try {
if (!cmd) {
const state = loadState();
if (!state) {
console.log('⚠️ Belum ada email aktif. Jalankan: node email.js --new');
} else {
console.log(`📧 Email aktif: ${state.address}`);
}
return;
}
switch (cmd) {
case '--new':
await createNewEmail(targetParam);
break;
case '--get':
await getInboxList(targetParam);
break;
case '--read':
await readMessageDetail(targetParam, extraParam);
break;
case '--help':
case '-h':
printHelp();
break;
default:
console.log(`⚠️ Command "${cmd}" nggak dikenal.`);
printHelp();
}
} catch (err) {
console.error('❌ Error:', err.message);
process.exit(1);
}
}
main();
Komentar (4)
Masuk untuk ikut berkomentar.