Java™ - Cara Download Lampiran pada Email dan Mengekstraknya Kembali via SMTPS Gmail
What Will I Learn?
Apa Yang Akan Saya Pelajari?
Pada tutorial kali ini, spesial dalam bahasa Indonesia, saya akan menjelaskan bagaimana cara membaca email pada suatu akun Google yang Anda miliki menggunakan program Java™. Selanjutnya, jika di dalam email itu ada lampiran berupa berkas zip, maka kita akan mengekstraknya ke direktori target yang telah ditentukan sebelumnya. Tetapi, sebelum Anda bisa mengikuti tutorial kali ini dengan baik, Anda harus menguasai tutorial sebelumnya yang terlampir pada Curriculum. Berikut adalah materi umum yang akan terkuasai dalam mengikuti tutorial ini.
- Java™ I/O Stream
- Java™ Mail
- Java™ Functional Interface
Requirements
Persyaratan
Pastikan Anda memasang (instalasi) perangkat lunak dan menyesuaikan pengaturan berikut:
Java™ Standard Edition Development Kit terbaru saat ini.
Akun Google yang Dijadikan Target.
Pastikan pada akun yang dijadikan target, untuk mengganti pengaturan
Allow less secure apps
menjadiOn
, di sini.
Difficulty
Tingkat Kesulitan
- Basic
Dasar
Tutorial Contents
Koneksi ke Folder
Inbox
Definisikan properti untuk mendapatkan koneksi ke server melalui SMTPS Gmail pada variabel statik
GMAIL
, seperti alamat host, port dan lainnya. Kemudian, buat sebuah metode dengan namaretrieve
, yang akan menerima dua buah parameter, yaituusername
danpassword
dari akun yang akan dilihat seluruh email-nya.Berikut adalah kode untuk mengambil dan membaca semua email sekaligus yang ada di folder
Inbox
:public static void retrieve(String username, String password) { Session session = Session.getDefaultInstance(GMAIL); try { Store store = session.getStore("imaps"); store.connect(GMAIL.getProperty("mail.smtp.host"), username, password); Folder inbox = store.getFolder("Inbox"); inbox.open(Folder.READ_ONLY); /* * Right now, the folder is ready */ { inbox.getMessages(); } inbox.close(false); store.close(); } catch(Throwable e) { e.printStackTrace(); } }
private static final java.util.Properties GMAIL = new java.util.Properties();
static { GMAIL.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); GMAIL.put("mail.smtp.socketFactory.port", "465"); GMAIL.put("mail.smtp.ssl.enable", "true"); GMAIL.put("mail.smtp.auth", "true"); GMAIL.put("mail.smtp.host", "smtp.gmail.com"); GMAIL.put("mail.smtp.port", "465"); }Membaca Input dari Pengguna
Program akan terus mengambil dan membaca email dari akun target sampai pengguna memberikan input
0
(nol). Di sini akan digunakan kelasjava.io.BufferedReader
untuk membaca setiap input sebagai baris dari pengguna melalui konsol. Cara menciptakan objek pembaca input adalah:BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)`.
Selanjutnya, jika pengguna memberikan input angka apa pun, maka program pembaca email ini akan melewatkan beberapa email yang akan dibaca sebanyak angka yang diberikan. Maka, kode di atas akan menjadi seperti berikut:
public static void retrieve(String username, String password) { Session session = Session.getDefaultInstance(GMAIL); try { Store store = session.getStore("imaps"); store.connect(GMAIL.getProperty("mail.smtp.host"), username, password); Folder inbox = store.getFolder("Inbox"); inbox.open(Folder.READ_ONLY); String line; int i = 0, n = inbox.getMessageCount(); try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))) { do { print(inbox.getMessage(n -= (i + 1))); System.out.print("To stop, type \"0\" (zero) or type any positive number to jump: "); line = reader.readLine(); try{ i = Integer.parseInt(line); } catch(Throwable e) { i = 0; } } while(!line.equals("0")); } inbox.close(false); store.close(); } catch(Throwable e) { e.printStackTrace(); } }
Daftarkan Fungsi Baru untuk Menangani Berkas Zip
Pada tutorial sebelumnya, kita telah mendaftarkan tiga fungsi untuk menangani berkas dengan tipe
multipart/*
, gambar dan selain itu semua. Maka akan ditambahkan sebuah fungsi lagi untuk menangani berkas zip.Periksa
MimeType
Tambahkan sebuah variabel statik
ZIP
untuk menyimpan konstantaapplication/zip
dan pada metodeprint
(Part
) selalu periksa tipe dari konten, jika sesuai denganZIP
atauapplication/x-rar-compressed
lakukan proses ekstraksi. Berikut adalah logikanya:
private static final Map<String, Function<Object, Void>> FUNCTIONS = new java.util.HashMap<>(); private static final String ZIP = "application/zip";
. . . else if(part.isMimeType(ZIP) || part.isMimeType("application/x-rar-compressed")) FUNCTIONS.get(ZIP).apply(part); . . .
Fungsi Ekstraksi Berkas Zip
Tambahkan kode berikut:
FUNCTIONS.put(ZIP, content -> { BodyPart body; Path newSrc, parent; InputStream in; FileOutputStream out; try { /* * Selalu minta ke pengguna di direktori mana berkas akan disimpan dan diekstrak */ BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); body = (BodyPart) content; System.out.print("Enter path and file name for attachment \"" + body.getFileName() + "\": "); newSrc = Paths.get(reader.readLine()); parent = newSrc.getParent(); /* * Selalu periksa dan buatkan direktori baru jika pengguna * memberikan direktori yang tidak pernah ada. */ if(Files.notExists(parent)) Files.createDirectories(parent); out = new FileOutputStream(newSrc.toFile()); in = body.getInputStream(); } catch(Throwable e) { e.printStackTrace(); return null; } final byte[] BYTES = new byte[2048]; try { /* * Proses download */ for(int length;(length = in.read(BYTES)) > -1;) out.write(BYTES, 0, length); out.close(); System.out.println("Download attachment was successful"); /** * Proses ekstraksi berkas yang telah selesai ter-download */ ZipIOStream.unzip(true, parent, newSrc); System.out.println("Extraction of " + newSrc + " was successful"); } catch(Throwable e) { e.printStackTrace(); } return null; });
Definisikan Metode Ekstraksi
Pada kelas
ZipIOStream
yang telah terdefinisikan sebelumnya di sini, buat sebuah metode privat baru dengan namaunzip
yang akan menerima parameterjava.util.zip.ZipInputStream
sebagaizipIn
, danjava.nio.file.Path
sebagai direktori target. Dan berikut ini adalah kodenya:private static void unzip(ZipInputStream zipIn, Path target) throws Throwable { ZipEntry entry = zipIn.getNextEntry(); final byte[] BYTES = new byte[2048]; for(Path newPath, parent; entry != null; entry = zipIn.getNextEntry()) { String name = entry.getName(); newPath = target.resolve(name); if(entry.isDirectory() || name.charAt(name.length() - 1) == separatorChar) Files.createDirectories(newPath); else { if(Files.notExists(parent = newPath.getParent())) Files.createDirectories(parent); Files.createFile(newPath); try(FileOutputStream out = new FileOutputStream(newPath.toFile()); FileLock lock = out.getChannel().lock()) { for(int length; (length = zipIn.read(BYTES)) > -1; ) out.write(BYTES, 0, length); lock.release(); } } } }
Metode di atas hanya dapat mengekstrak sebuah berkas zip, karena hal ini metode tersebut didefinisikan privat. Selanjutnya kita akan mendefinisikan sebuah metode global yang akan dapat mengekstrak banyak berkas sekaligus. Berikut adalah kodenya:
/** * Mengekstrak berkas zip. * @param thrown - Apakah akan melemparkan Exception jika terjadi kesalahan, atau tidak. * @param target - Direktori target di mana hasil ekstraksi akan dimuat. * @param source - Berkas-berkas zip yang akan diekstrak. * @return - {@code True} jika proses ekstraksi berhasil, sebaliknya {@code false}. */ public static boolean unzip(boolean thrown, Path target, Path... source) { if(Files.notExists(target)) try { Files.createDirectories(target); } catch(Throwable e) { if(thrown) throw new RuntimeException(e); return false; } else if(Files.isRegularFile(target)) target = target.getParent(); boolean b = true; for(Path p : source) try(ZipInputStream reader = new ZipInputStream(new FileInputStream(p.toFile()))) { unzip(reader, target); } catch(Throwable e) { if(thrown) throw new RuntimeException(e); b = false; } return b; }
Pengujian
Pengujian ini masih menggunakan metode Main
yang sama seperti sebelumnya.
Email Target
Berikut adalah email target yang akan dibaca kontennya, di-download (Test.zip
), dan akhirnya diekstrak.
Log
Hasil
Selamat! Akhirnya kita berhasil men-download berkas zip dan mengekstraknya kembali, serta menyelesaikan tutorial ini dengan baik.
Terima Kasih!
Share with Heart.
Curriculum
Posted on Utopian.io - Rewarding Open Source Contributors
Your contribution cannot be approved because it does not follow the Utopian Rules.
You have already shared this post in another language. This is a duplicate.
You can contact us on Discord.
[utopian-moderator]
Hello @deathwing,
You did not actually review my contribution in detail.
This is a series in order to manipulate email in Java apps, and now about retrieving and unzipping.
But you've said that it was duplicate in another language.