diff --git a/README.md b/README.md
index 14fe824..6d783a0 100644
--- a/README.md
+++ b/README.md
@@ -11,17 +11,15 @@
2024.10.12 - 2024.11.06
### ๐งโ๐คโ๐ง ๊ตฌ์ฑ์
- - Team Leader: ๊นํ์ฐ
- - Member 2: ๋ฐ๋ฏผ์
+ - Team Leader 1: ๊นํ์ฐ
+ - Team Leader 2: ๋ฐ๋ฏผ์
- Member 3: ํ์ง๋ฏผ
- Member 4: ์ด์ํ
- Member 5: ์ ์๋ฆฐ
### โ๏ธ ๊ฐ๋ฐํ๊ฒฝ
- - Java Version: `JDK22`
- - IDE:
- - Framework:
- - ORM:
+ - Java Version: `JDK 22`
+ - IDE: `Eclips 4.33.0`
## ๐ ํ๋ก์ ํธ ๊ตฌ์ฑ
@@ -35,336 +33,1163 @@ src
โโโ FileHandler.java
โโโ MimeMessageBuilder.java
โโโ email.smtp
- โโโ Auth.java
โโโ Client.java
- โโโ email.main
- โโโ EmailApp.java
+ โโโ EmailServiceWithNaver.java
+ โโโ EmailWithNaver.java
+ lib
+ โโโ flatlaf-3.5.2.jar
```
## ๐ ์ฃผ์ ๊ธฐ๋ฅ
1. **๋ก๊ทธ์ธ**
- - ์ฌ์ฉ์๊ฐ `LoginGUI`์์ ์ด๋ฉ์ผ๊ณผ ๋น๋ฐ๋ฒํธ๋ฅผ ์
๋ ฅํฉ๋๋ค.
- - ์
๋ ฅ๋ ์ด๋ฉ์ผ์ `Auth` ๊ฐ์ฒด์ ์ ๋ฌ๋์ด ์ฌ๋ฐ๋ฅธ ์ด๋ฉ์ผ ์ฃผ์์ธ์ง ํ์ธํฉ๋๋ค.
- - ์ด๋ฉ์ผ ์ฃผ์๊ฐ ์ ํจํ๊ณ ์ฐ๊ฒฐ์ด ์ฑ๊ณตํ๋ฉด `SendEmailGUI`๊ฐ ์คํ๋ฉ๋๋ค.
+ - ์ฌ์ฉ์๋ `LoginGUI`์์ ์ ๊ณตํ๋ ์ด๋ฉ์ผ๊ณผ ๋น๋ฐ๋ฒํธ ์
๋ ฅ ํ๋์ ์ด๋ฉ์ผ๊ณผ ๋น๋ฐ๋ฒํธ๋ฅผ ์
๋ ฅํ ํ, Login ๋ฒํผ์ ๋๋ฆ
๋๋ค.
+ - ์
๋ ฅ๋ ์ด๋ฉ์ผ์ ๊ฐ์ฒด์ ์ ๋ฌ๋๊ณ , `LoginGUI`๋ ์
๋ ฅ๋ ์ด๋ฉ์ผ์ด ์ฌ๋ฐ๋ฅธ ์ด๋ฉ์ผ ์ฃผ์์ธ์ง ํ์ธํฉ๋๋ค.
+ - ์ด๋ฉ์ผ ์ฃผ์๊ฐ ์ ํจํ๊ณ , ์ฐ๊ฒฐ์ ์ฑ๊ณตํ๋ฉด `SendEmailGUI`๊ฐ ์คํ๋ฉ๋๋ค.
2. **์ด๋ฉ์ผ ์ ์ก**
- - `SendEmailGUI`์์ ์ฌ์ฉ์๋ ์ด๋ฉ์ผ ๋ฉ์์ง์ ์ฒจ๋ถํ ํ์ผ์ ์ ํํฉ๋๋ค.
- - ์ฌ์ฉ์๊ฐ ์ ์ก ๋ฒํผ์ ํด๋ฆญํ๋ฉด `Client` ํด๋์ค๊ฐ ํธ์ถ๋์ด, ์
๋ ฅ๋ ๋ฉ์์ง์ ํ์ผ์ ๋ํ Base64 ์ธ์ฝ๋ฉ ๋ฑ์ ์ฒ๋ฆฌ๋ฅผ ์ํํฉ๋๋ค.
- - ์ฒ๋ฆฌ๋ ๋ด์ฉ์ด ์ฌ๋ฐ๋ฅธ์ง ๊ฒ์ฆ ํ, ์ต์ข
์ ์ผ๋ก ์ด๋ฉ์ผ์ด ์ ์ก๋ฉ๋๋ค.
+ - `SendEmailGUI`์์ ์ฌ์ฉ์๋ ์์ ์, ์ ๋ชฉ, ๋ฉ์์ง๋ฅผ ์
๋ ฅํฉ๋๋ค. Attach File ๋ฒํผ์ ๋๋ฌ ์ฒจ๋ถํ ํ์ผ์ ์ ํํ ์ ์์ต๋๋ค.
+ - ์ฌ์ฉ์๊ฐ Send ๋ฒํผ์ ํด๋ฆญํ๋ฉด `Client` ํด๋์ค๊ฐ ํธ์ถ๋์ด, ์
๋ ฅ๋ ๋ฉ์์ง์ ํ์ผ์ ๋ํ Base64 ์ธ์ฝ๋ฉ, MIMEํ์์ผ๋ก ๋ณํ ์ฒ๋ฆฌ๊ฐ ์ํ๋ฉ๋๋ค.
+ - ์์ ์, ์ ๋ชฉ, ๋ฉ์์ง๊ฐ ์ฌ๋ฐ๋ฅธ์ง ๊ฒ์ฆํ ํ, ์ ํ๋ ํ์ผ๊ณผ ํจ๊ป ์ต์ข
์ ์ผ๋ก ์ด๋ฉ์ผ์ด ์ ์ก๋ฉ๋๋ค.
+ - ํ๋ฒ์ ์ฌ๋ฌ ์ฌ์ฉ์์๊ฒ ๋ฉ์ผ์ ์ ์กํ ์ ์์ต๋๋ค.
+ - Quit ๋ฒํผ ํด๋ฆญ ์, SMTP ์๋ฒ ์ฐ๊ฒฐ์ ์ข
๋ฃํ๊ณ ํ๋ก๊ทธ๋จ์ด ์ข
๋ฃ๋ฉ๋๋ค.
-4. **ํ์ผ ์ฒจ๋ถ**
- - ์ฌ์ฉ์๊ฐ ์ฒจ๋ถํ ์ ์๋ ํ์ผ์ ํ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- - ์ด๋ฏธ์ง ํ์ผ (jpg, png ๋ฑ)
- - ๋ฌธ์ ํ์ผ (pdf, docx ๋ฑ)
- - ํ
์คํธ ํ์ผ (txt ๋ฑ)
+3. **ํ์ผ ์ฒจ๋ถ**
+ - `FileHandler`์์ ํ์ผ์ด ์ ํจํ์ง, MIME ํ์
์ด ์ ํจํ์ง ๊ฒ์ฌํฉ๋๋ค. (์ ํจํ ํ์ผ ํ์: ์ด๋ฏธ์ง ํ์ผ, PDF, ํ
์คํธ ํ์ผ)
+ - ์กฐ๊ฑด์ด ์ถฉ์กฑ๋๋ฉด ํ์ผ์ด ์ฒจ๋ถ๋์๋ค๋ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
+ - ํ์ผ์ด ์กด์ฌํ์ง ์์ผ๋ฉด ํ์ผ์ด ์๋ค๋ ๋ฉ์์ง๋ฅผ ์ถ๋ ฅํฉ๋๋ค.
+
## ๐ ํจํค์ง ์์ธ ์ค๋ช
-### 1. `email.gui`
-
- LoginGUI.java
+### 1. *email.gui*
- ```javascript
-
- ```
-
-
-
- SendEmailGUI.java
-
- ```javascript
-
- ```
-
-
-- `LoginGUI.java`: ์ฌ์ฉ์ ๋ก๊ทธ์ธ ์ธํฐํ์ด์ค
-- `SendEmailGUI.java`: ์ด๋ฉ์ผ ์ ์ก ์ธํฐํ์ด์ค
-
-### 2. `email.mime`
-
- FileHandler.java
-
- ```javascript
- package email.mime;
-
- import java.nio.file.Files;
- import java.nio.file.Path;
- import java.nio.file.Paths;
- import java.io.File;
- import java.io.IOException;
- import java.nio.file.StandardCopyOption;
-
- public class FileHandler {
-
- // ํ์ผ์ ์ฒจ๋ถํ๋ ๋ฉ์๋
- // filePath๋ก ์ง์ ๋ ํ์ผ์ ์ฒจ๋ถํ ์ ์๋์ง ํ์ธ ํ ์ฒ๋ฆฌ
- public void attachFile(String filePath) {
- File file = new File(filePath);
- if (file.exists()) {
- if (isValidFileType(file)) {
- // ์ ํจํ ํ์ผ์ด๋ฉด ์ฒจ๋ถ
- } else {
- System.out.println("์ ํจํ์ง๊ฐ ์์์."); // ์ค๋ฅ ๋ฉ์์ง ์ถ๋ ฅ
- }
- } else {
- System.out.println("ํ์ผ์ด ์์์."); // ํ์ผ์ด ์๋ ๊ฒฝ์ฐ ๋ฉ์์ง ์ถ๋ ฅ
- }
- }
-
- // ํ์ผ์ MIME ํ์
์ ๋ฐํํ๋ ๋ฉ์๋
- // ํ์ผ ๊ฒฝ๋ก๋ฅผ ์
๋ ฅ๋ฐ์ ํด๋น ํ์ผ์ MIME ํ์
์ ๋ฐํ
- // javax.activation์ผ๋ก๋ ๊ตฌํํ๋๊ฒ ์๊ธดํ๋ฐ ์ด๊ฒ ๊ธฐ๋ณธ jdk๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋น ์ ธ์์ด์ ๋ณ๋์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ์ถ๊ฐํด์ผํจ.
- // ์ฅ๋จ์ ๋น๊ต mimeํํธ๋ ๋
ผ์ ํ์ํ ๋ฏ
- public String getMimeType(String filePath) {
- Path path = Paths.get(filePath);
- try {
- return Files.probeContentType(path); // MIME ํ์
ํ์ง
- } catch (IOException e) {
- e.printStackTrace(); // ์ค๋ฅ ๋ฐ์ ์ ์ถ๋ ฅ
- return "์ด์ํ ํ์
์ธ๋ฐ์"; // ์ ์ ์๋ ๊ฒฝ์ฐ ์ฒ๋ฆฌ
- }
- }
-
- // ํ์ผ ํ์
์ ํจ์ฑ ํ์ธ ๋ฉ์๋
- // ์ด๋ฏธ์ง, PDF, ํ
์คํธ ํ์ผ์ด ์ ํจํ ํ์ผ ํ์
์ผ๋ก ๊ฐ์ฃผ๋จ
- public boolean isValidFileType(File file) {
- String mimeType = getMimeType(String.valueOf(file)); // MIME ํ์
๊ฐ์ ธ์ค๊ธฐ
- boolean isValid = false;
- if(mimeType.startsWith("image")) {
- isValid = true;
- } // image๋ง ์ผ๋จ ํ๋๋ฐ ๋ญ ํ์ผ ํ์ ์ฌ๋ฌ๊ฐ ํด์ผ๊ฒ ์ฅฌ
- return isValid;
- }
-
- // ํ์ผ ํฌ๊ธฐ ํ์ธ ๋ฉ์๋
- // ์ฃผ์ด์ง ํ์ผ ๊ฒฝ๋ก์ ๋ํ ํ์ผ ํฌ๊ธฐ๋ฅผ ๋ฐํ
- public long getFileSize(String filePath) {
- File file = new File(filePath);
- if (file.exists()) {
- return file.length(); // ํ์ผ ํฌ๊ธฐ ๋ฐํ
- } else {
- System.out.println("ํ์ผ์ด ์์์์"); // ํ์ผ์ ์ฐพ์ ์ ์๋ ๊ฒฝ์ฐ
- return 0;
- }
- }
+- **LoginGUI.java**
+
+ LoginGUI.java
+
+ ```javascript
+ package email.gui;
+
+ import javax.swing.*; // Swing ์ปดํฌ๋ํธ ์ฌ์ฉ์ ์ํ import
+ import javax.swing.border.EmptyBorder;
+ import java.awt.*;
+
+ import java.awt.event.ActionEvent; // ActionEvent ์ฌ์ฉ์ ์ํ import
+ import java.awt.event.ActionListener; // ActionListener ์ธํฐํ์ด์ค ์ฌ์ฉ์ ์ํ import
+ import java.awt.event.FocusAdapter;
+ import java.awt.event.FocusEvent;
+ import java.io.IOException;
+
+ import email.smtp.*; // ํด๋์ค import
+
+ public class LoginGUI {
+ private JFrame frame; // ๋ก๊ทธ์ธ ์ฐฝ์ ์ํ JFrame
+ private JTextField emailField; // ์ด๋ฉ์ผ ์
๋ ฅ ํ๋๋ฅผ ์ํ JTextField
+ private JPasswordField passwordField; // ๋น๋ฐ๋ฒํธ ์
๋ ฅ ํ๋๋ฅผ ์ํ JPasswordField
+ private JButton loginButton; // ๋ก๊ทธ์ธ ๋ฒํผ์ ์ํ JButton
+ private JLabel errorLabel; // ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํ์ํ JLabel
+
+
+ // LoginGUI ์์ฑ์
+ public LoginGUI() {
+ initComponents(); // ์ปดํฌ๋ํธ ์ด๊ธฐํ ๋ฉ์๋ ํธ์ถ
+ }
+
+ // ๋ก๊ทธ์ธ ํ๋ฉด์ ํ์ํ๋ ๋ฉ์๋
+ public void display() {
+ frame.setVisible(true); // ํ๋ ์์ ๋ณด์ด๋๋ก ์ค์
+ }
+
+ // GUI ์ปดํฌ๋ํธ๋ฅผ ์ด๊ธฐํํ๋ ๋ฉ์๋
+ private void initComponents() {
+ frame = new JFrame("๋ก๊ทธ์ธ"); // ์ฐฝ ์ด๋ฆ ๋ณ๊ฒฝ
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // ์ฐฝ ๋ซ๊ธฐ ๋์ ์ค์
+ frame.setSize(700, 450); // ์ฐฝ ํฌ๊ธฐ ์ค์
+ frame.setLocationRelativeTo(null); // ๊ฐ์ด๋ฐ ์ ๋ ฌ
+
+ // E-mail ํ๋ ์์ฑ
+ emailField = createHintTextField("์ด๋ฉ์ผ์ ์
๋ ฅํ์ธ์", 1, new Color(179, 182, 197), new Color(255,255,255)); // ํํธ ํ
์คํธ๊ฐ ์๋ JTextField ์์ฑ
+ passwordField = createHintPasswordField("๋น๋ฐ๋ฒํธ๋ฅผ ์
๋ ฅํ์ธ์", 1, new Color(179, 182, 197), new Color(255,255,255));
+
+ loginButton = new JButton("Login"); // ๋ก๊ทธ์ธ ๋ฒํผ ์์ฑ
+ loginButton.setHorizontalAlignment(SwingConstants.CENTER); // ์ค์ ์ ๋ ฌ
+ loginButton.setVerticalAlignment(SwingConstants.CENTER); // ์ค์ ์ ๋ ฌ
+
+ // ๋ฒํผ ๋ฐฐ๊ฒฝ์๊ณผ ๊ธ์จ ์์ ์ค์
+ loginButton.setBackground(new Color(204, 122, 136)); // ๋ฐฐ๊ฒฝ์ ์ง์
+ loginButton.setForeground(Color.WHITE); // ๊ธ์จ์ (ํฐ์)
+
+ errorLabel = new JLabel(); // ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํ์ํ ๋ ์ด๋ธ ์์ฑ
+
+ loginButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ onLoginButtonClick(); // ๋ก๊ทธ์ธ ๋ฒํผ ํด๋ฆญ ์ ํธ์ถ๋๋ ๋ฉ์๋
+ }
+ });
+
+ // ๋ฒํผ ์ฃผ์์ ๊ณต๋ฐฑ ์ถ๊ฐ
+ loginButton.setBorder(BorderFactory.createCompoundBorder(
+ loginButton.getBorder(),
+ BorderFactory.createEmptyBorder(10, 80, 10, 80) // ์, ์ผ์ชฝ, ์๋, ์ค๋ฅธ์ชฝ ๊ณต๋ฐฑ ์ค์
+ ));
+
+ setLayout(); // ๋ ์ด์์ ์ค์
+ }
+
+ // ๋ก๊ทธ์ธ ๋ฒํผ ํด๋ฆญ ์ ํธ์ถ๋๋ ๋ฉ์๋
+ private void onLoginButtonClick() {
+ String email = emailField.getText(); // ์ด๋ฉ์ผ ์
๋ ฅ๊ฐ ๊ฐ์ ธ์ค๊ธฐ
+ String password = new String(passwordField.getPassword()); // ๋น๋ฐ๋ฒํธ ์
๋ ฅ๊ฐ ๊ฐ์ ธ์ค๊ธฐ
+
+ // ์ด๋ฉ์ผ๊ณผ ๋น๋ฐ๋ฒํธ๊ฐ ๋น์ด ์๋์ง ํ์ธ
+ if (email.isEmpty() || password.isEmpty()) {
+ showError("์ด๋ฉ์ผ ๋๋ ๋น๋ฐ๋ฒํธ๋ฅผ ์
๋ ฅํ์ธ์.");
+ return;
+ }
+
+ // ์ด๋ฉ์ผ ํ์ ๊ฒ์ฆ
+ if (!isValidEmail(email)) {
+ showError("์ด๋ฉ์ผ ์ฃผ์ ํ์์ด ์ฌ๋ฐ๋ฅด์ง ์์ต๋๋ค. \n์์: ํ๊ธธ๋@naver.com ๊ผด๋ก ์
๋ ฅํด์ฃผ์ธ์.");
+ return; // ์ ํจํ์ง ์์ ๊ฒฝ์ฐ ๋ฐํ
+ }
+
+ System.out.println("์ด๋ฉ์ผ : " + email + " ๋น๋ฐ๋ฒํธ : " + password + " ์
๋ ฅ์๋ฃ!");
+ // Client ์ธ์คํด์ค ์์ฑ
+ Client client = new Client(email, password);
+
+ // ์ด๋ฉ์ผ ๋๋ฉ์ธ ๊ฒ์ฆ
+ if (!client.mailService.isCorrectAddress()) {
+ showError("์ง์ํ์ง ์๋ ์ด๋ฉ์ผ ๋๋ฉ์ธ์
๋๋ค. @naver.com์ ์ฌ์ฉํ์ธ์.");
+ return; // ์ ํจํ์ง ์์ ๊ฒฝ์ฐ ๋ฐํ
+ }
+
+ // ์ธ์ฆ ์๋
+ try {
+ client.mailService.connect();
+ // ์ธ์ฆ ์๋
+ JOptionPane.showMessageDialog(frame, "๋ก๊ทธ์ธ ์ฑ๊ณต!"); // ์ฑ๊ณต ๋ฉ์์ง ํ์
+ clearFields(); // ํ๋ ์ด๊ธฐํ
+ frame.dispose(); // ๋ก๊ทธ์ธ ์ฐฝ ๋ซ๊ธฐ
+
+ // SendEmailGUI ์ธ์คํด์ค ์์ฑ ๋ฐ ํ์
+ SendEmailGUI sendEmailGUI = new SendEmailGUI(client,this); // SendEmailGUI ์์ฑ
+ sendEmailGUI.display(); // SendEmailGUI ํ์
+ } catch (IOException e) {
+ showError(e.getMessage()); // ์์ธ ๋ฉ์์ง๋ฅผ ์ฌ์ฉ์์๊ฒ ํ์
+ } catch (HeadlessException e) {
+ e.printStackTrace(); // ์ค๋ฅ ์คํ ํธ๋ ์ด์ค ์ถ๋ ฅ
+ showError("์ค๋ฅ๊ฐ ๋ฐ์ํ์ต๋๋ค. ๋ค์ ์๋ํด์ฃผ์ธ์."); // ์ผ๋ฐ ์ค๋ฅ ๋ฉ์์ง ํ์
+ }
+ }
+
+ // ์ด๋ฉ์ผ ์ฃผ์์ ์ ํจ์ฑ ๊ฒ์ฌ
+ private boolean isValidEmail(String email) {
+ String emailRegex = "^[\\w-\\.]+@[\\w-]+\\.[a-zA-Z]{2,}$"; // ์ด๋ฉ์ผ ์ ๊ท ํํ์
+ return email.matches(emailRegex);
+ }
+
+ // ์ค๋ฅ ๋ฉ์์ง๋ฅผ ํ์
์ผ๋ก ๋ณด์ฌ์ฃผ๋ ๋ฉ์๋
+ private void showError(String message) {
+ errorLabel.setText(message); // ์ค๋ฅ ๋ฉ์์ง๋ฅผ ์ค์
+ JOptionPane.showMessageDialog(frame, message, "์ค๋ฅ", JOptionPane.ERROR_MESSAGE); // ํ์
์ผ๋ก ์ค๋ฅ ๋ฉ์์ง ํ์
+ }
+
+ // ์
๋ ฅ ํ๋๋ฅผ ์ด๊ธฐํํ๋ ๋ฉ์๋
+ private void clearFields() {
+ emailField.setText(""); // ์ด๋ฉ์ผ ํ๋ ์ด๊ธฐํ
+ passwordField.setText(""); // ๋น๋ฐ๋ฒํธ ํ๋ ์ด๊ธฐํ
+ }
+
+
+
+ // ํํธ ํ
์คํธ๊ฐ ์๋ JTextField ์์ฑ ๋ฉ์๋
+ private JTextField createHintTextField(String hint, int columns, Color backgroundColor, Color foregroundColor) {
+ JTextField textField = new JTextField(columns); // JTextField ์์ฑ
+ textField.setBackground(backgroundColor); // ๋ฐฐ๊ฒฝ ์์ ์ค์
+ textField.setForeground(foregroundColor); // ๊ธ์จ ์์ ์ค์
+
+
+ // ํํธ ํ
์คํธ ์ด๊ธฐํ
+ textField.setText(hint);
+ textField.setForeground(Color.GRAY); // ํํธ ์์ ์ค์
+
+ // ํฌ์ปค์ค ๋ฆฌ์ค๋ ์ถ๊ฐ
+ textField.addFocusListener(new FocusAdapter() {
+ @Override
+ public void focusGained(FocusEvent e) {
+ // ํ๋๊ฐ ํฌ์ปค์ค๋ฅผ ๋ฐ์ ๋ ํํธ ํ
์คํธ ์ง์ฐ๊ธฐ
+ if (textField.getText().equals(hint)) {
+ textField.setText("");
+ textField.setForeground(Color.BLACK); // ๊ธ์จ ์์ ๋ณ๊ฒฝ
+ }
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+ // ํ๋๊ฐ ํฌ์ปค์ค๋ฅผ ์์ ๋ ํํธ ํ
์คํธ๊ฐ ๋น์ด์์ผ๋ฉด ๋ค์ ์ค์
+ if (textField.getText().isEmpty()) {
+ textField.setForeground(Color.GRAY); // ํํธ ์์ ์ค์
+ textField.setText(hint);
+ }
+ }
+ });
+
+ return textField; // ์ค์ ๋ JTextField ๋ฐํ
+ }
+
+ // ํํธ ํ
์คํธ๊ฐ ์๋ JPasswordField ์์ฑ ๋ฉ์๋
+ private JPasswordField createHintPasswordField(String hint, int columns, Color backgroundColor, Color foregroundColor) {
+ JPasswordField passwordField = new JPasswordField(columns); // JPasswordField ์์ฑ
+ passwordField.setBackground(backgroundColor); // ๋ฐฐ๊ฒฝ ์์ ์ค์
+ passwordField.setForeground(foregroundColor); // ๊ธ์จ ์์ ์ค์
+
+
+ // ํํธ ํ
์คํธ ์ด๊ธฐํ
+ passwordField.setText(hint);
+ passwordField.setForeground(Color.GRAY); // ํํธ ์์ ์ค์
+
+ // ํฌ์ปค์ค ๋ฆฌ์ค๋ ์ถ๊ฐ
+ passwordField.addFocusListener(new FocusAdapter() {
+ @Override
+ public void focusGained(FocusEvent e) {
+ // ํ๋๊ฐ ํฌ์ปค์ค๋ฅผ ๋ฐ์ ๋ ํํธ ํ
์คํธ ์ง์ฐ๊ธฐ
+ if (new String(passwordField.getPassword()).equals(hint)) {
+ passwordField.setText("");
+ passwordField.setForeground(Color.BLACK); // ๊ธ์จ ์์ ๋ณ๊ฒฝ
+ }
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+ // ํ๋๊ฐ ํฌ์ปค์ค๋ฅผ ์์ ๋ ํํธ ํ
์คํธ๊ฐ ๋น์ด์์ผ๋ฉด ๋ค์ ์ค์
+ if (new String(passwordField.getPassword()).isEmpty()) {
+ passwordField.setForeground(Color.GRAY); // ํํธ ์์ ์ค์
+ passwordField.setText(hint);
+ }
+ }
+ });
+
+ return passwordField; // ์ค์ ๋ JPasswordField ๋ฐํ
+ }
+
+
+ // ๋ ์ด์์์ ์ค์ ํ๋ ๋ฉ์๋
+ private void setLayout() {
+ JPanel panel = new JPanel(); // ํจ๋ ์์ฑ
+ frame.add(panel); // ํจ๋์ ํ๋ ์์ ์ถ๊ฐ
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); // ์์ง ๋ ์ด์์ ์ค์
+ panel.setBackground(new Color(56,62,88)); // ๋ฐฐ๊ฒฝ ์ ์ค์
+ panel.setBorder(new EmptyBorder(40,50,10,50)); // ํจ๋ฉ
+
+
+ // ์๋จ ๋ฉํธ
+ JLabel label_0 = new JLabel("Welcome!");
+ Font currentFont = label_0.getFont();
+ label_0.setFont(currentFont.deriveFont(36f)); // ํฌ๊ธฐ๋ฅผ 36์ผ๋ก ์ค์
+ label_0.setForeground(Color.white); // ๊ธ์จ ์์ ์ค์
+ panel.add(label_0);
+ label_0.setBorder(new EmptyBorder(0,0,10,0)); // ์๋ ๊ฐ๊ฒฉ 10
+
+ JLabel label_1 = new JLabel("This is Email Sending Program!");
+ label_1.setFont(currentFont.deriveFont(20f)); // ํฌ๊ธฐ๋ฅผ 20์ผ๋ก ์ค์
+ label_1.setForeground(new Color(177, 181, 193)); // ๊ธ์จ ์์ ์ค์
+ panel.add(label_1);
+ label_1.setBorder(new EmptyBorder(0,0,30,0)); // ์๋ ๊ฐ๊ฒฉ 40
+
+ JLabel label_2 = new JLabel("Please enter your E-mail address and password.");
+ label_2.setFont(currentFont.deriveFont(14f)); // ํฌ๊ธฐ๋ฅผ 14์ผ๋ก ์ค์
+ label_2.setForeground(new Color(204, 122, 136)); // ๊ธ์จ ์์ ์ค์
+ panel.add(label_2);
+ label_2.setBorder(new EmptyBorder(0,0,9,0)); // ์๋ ๊ฐ๊ฒฉ 9
+
+ // ์ด๋ฉ์ผ ๋ ์ด๋ธ ์ถ๊ฐ
+ JLabel emailLabel = new JLabel("E-MAIL");
+ emailLabel.setFont(currentFont.deriveFont(Font.BOLD,20f)); // ํฌ๊ธฐ๋ฅผ 20์ผ๋ก ์ค์
+ emailLabel.setForeground(Color.white); // ๊ธ์จ ์์ ์ค์
+ panel.add(emailLabel);
+ emailLabel.setBorder(new EmptyBorder(0,0,11,0)); // ์๋ ๊ฐ๊ฒฉ 11
+
+
+ panel.add(emailField); // ์ด๋ฉ์ผ ์
๋ ฅ ํ๋ ์ถ๊ฐ
+
+
+ // ์ด๋ฉ์ผ ๋ ์ด๋ธ ์ถ๊ฐ
+ JLabel passwordLabel = new JLabel("PASSWORD");
+ passwordLabel.setFont(currentFont.deriveFont(Font.BOLD,20f)); // ํฌ๊ธฐ๋ฅผ 20์ผ๋ก ์ค์
+ passwordLabel.setForeground(Color.white); // ๊ธ์จ ์์ ์ค์
+ panel.add(passwordLabel);
+ passwordLabel.setBorder(new EmptyBorder(21,0,11,0)); // ์๋ ๊ฐ๊ฒฉ 11
+
+
+ panel.add(passwordField); // ๋น๋ฐ๋ฒํธ ์
๋ ฅ ํ๋ ์ถ๊ฐ
+
+ // ๋ฒํผ ํจ๋ ์์ฑ ๋ฐ FlowLayout ์ค์
+ JPanel buttonPanel = new JPanel(new FlowLayout()); // ๋ฒํผ ํจ๋ ์์ฑ
+ buttonPanel.setBackground(new Color(56,62,88)); // ๋ฐฐ๊ฒฝ ์ ์ค์
+ buttonPanel.add(loginButton); // sendButton ์ถ๊ฐ
+
+ buttonPanel.setAlignmentX(JPanel.LEFT_ALIGNMENT); // ์ผ์ชฝ ์ ๋ ฌ
+
+ panel.add(buttonPanel); // ๋ฒํผ ํจ๋์ ๋ฉ์ธ ํจ๋์ ์ถ๊ฐ
+
+ panel.add(Box.createRigidArea(new Dimension(0, 20))); // ์ฌ๋ฐฑ
+ //panel.add(loginButton); // ๋ฒํผ ์ถ๊ฐ
+ panel.add(Box.createRigidArea(new Dimension(0, 1))); // ์ฌ๋ฐฑ
+
+ errorLabel.setForeground(new Color(204,122,136)); // ๊ธ์จ ์์ ์ค์
+ panel.add(errorLabel); // ์ค๋ฅ ๋ฉ์์ง ๋ ์ด๋ธ ์ถ๊ฐ
+
+ }
+ }
+
+
+ ```
+
- // ํ์ผ ์ฒจ๋ถ ํ ํ์ผ ๋ชฉ๋ก์ ๊ด๋ฆฌํ๋ ๋ฉ์๋
- public void manageAttachedFiles() {
- // ๋ฆฌ์คํธ์ ํ์ผ์ ์ถ๊ฐํ๊ฑฐ๋, ์ญ์ ํ๊ฑฐ๋, ์ถ๋ ฅํ๋ ๊ธฐ๋ฅ ํฌํจ ์์
- // ํ ๋ฉ์๋์ ๋ฃ์ง ๋ง๊ณ ๋๋๊น? ์ข ๊ธธ์ด์ง๊ฑฐ ๊ฐ๊ธด ํจ๋๋ค
- }
- // ํ์ผ์ ๋ก์ปฌ ๋์คํฌ์ ์ ์ฅํ๋ ๋ฉ์๋
- public void saveFileToDisk(File file, String destinationDirectory) throws IOException {
- // ํ์ผ์ด ์ ํจํ์ง ํ์ธ ํ ์ ์ฅ ์์
- Path destinationPath = Path.of(destinationDirectory, file.getName());
- Files.copy(file.toPath(), destinationPath, StandardCopyOption.REPLACE_EXISTING);
- }
- }
+ - GUI component ์์ฑ โ ์ฌ์ฉ์ ์
๋ ฅ ๊ฒ์ฆ, ์ด๋ฉ์ผ ๋๋ฉ์ธ ๋ฐ ํ์ ํ์ธ โ ๋ก๊ทธ์ธ ์ฑ๊ณตํ๋ฉด `SendEmailGUI` ์คํ
+
+ - `display()`
+ - main class์์ `display()`๋ฅผ ํธ์ถ ์ Login ์ฐฝ ํ์
+ - `initComponents()`
+ - ๋ชจ๋ GUI component ์ด๊ธฐํ
+ - Login ๋ฒํผ์ ๋ํ `ActionListener()` ๋ฑ๋ก โ ๋ฒํผ ํด๋ฆญ ์ `onLoginButtonClick()` ํธ์ถ
+ - ์ด๋ฉ์ผ ์
๋ ฅ ํ๋, ๋น๋ฐ๋ฒํธ ์
๋ ฅ ํ๋๋ฅผ ํํธ ํ
์คํธ๊ฐ ์๋ `JTextField` `JPasswordField`๋ก ์ค์
+ - `onLoginButtonClick()`
+ - Login ๋ฒํผ ํด๋ฆญ โ ์ด๋ฉ์ผ ๋น๋ฐ๋ฒํธ ์
๋ ฅ ์ฌ๋ถ ํ์ธ, ์ด๋ฉ์ผ ํ์์ด ์ ํจํ์ง ๊ฒ์ฌ
+ - **์ฌ๋ฐ๋ฅด์ง ์์ ์ด๋ฉ์ผ ํ์, ๋น ์
๋ ฅ ๊ฐ**: `showError()`๋ฅผ ํตํด ์ค๋ฅ ๋ฉ์์ง ํ์
+ - **์ฌ๋ฐ๋ฅธ ์ด๋ฉ์ผ ํ์**: Client ๊ฐ์ฒด ์์ฑ, ์ด๋ฉ์ผ ์๋น์ค ๋๋ฉ์ธ์ด ์ฌ๋ฐ๋ฅธ์ง ํ์ธ โ ์ ํจํ ๋๋ฉ์ธ: SMTP ์๋ฒ์ ์ฐ๊ฒฐ ์๋ โ ์ฐ๊ฒฐ ์ฑ๊ณตํ๋ฉด ์ด๋ฉ์ผ ์ ์ก GUI ํ๋ฉด ์ถ๋ ฅ
+ - `createHintTextField()` `createHintPasswordField()`
+ - ํํธ ํ
์คํธ๊ฐ ํฌํจ๋ `JTextField` `JPasswordField` ์์ฑ
- ```
-
+
+- **SendEmailGUI.java**
+
+ SendEmailGUI.java
+
+ ```javascript
+ package email.gui;
+
+ import javax.swing.*;
+ import javax.swing.border.EmptyBorder;
+
+ import java.awt.Color;
+ import java.awt.Dimension;
+ import java.awt.FlowLayout;
+ import java.awt.Font;
+ import java.awt.event.ActionEvent;
+ import java.awt.event.ActionListener;
+ import java.io.File;
+ import java.io.IOException;
+
+ import java.util.concurrent.*;
+
+ import email.smtp.Client;
+ import email.smtp.EmailServiceWithNaver;
+ import email.mime.FileHandler;
+
+ public class SendEmailGUI {
+ private JFrame frame;
+ private JTextField recipientField;
+ private JTextField subjectField;
+ private JTextArea messageArea;
+ private JButton sendButton;
+ private JButton attachButton;
+ private JButton quitButton; // quit ๋ฒํผ ์ถ๊ฐ
+ private JTextField fileField;
+ private JLabel statusLabel;
+ private JLabel errorLabel;
+ private File attachedFile;
+ private Client client;
+ private FileHandler fileHandler; // File handling utility
+ private ScheduledExecutorService noopScheduler;
+ private LoginGUI loginGUI;
+ public SendEmailGUI(Client client,LoginGUI loginGUI) {
+ this.client = client;
+ this.fileHandler = new FileHandler();
+ this.loginGUI = loginGUI;
+ initComponents();
+ startNoopScheduler();
+ }
+
+ public void display() {
+ frame.setVisible(true);
+ }
+ public void unDisplay() {
+ frame.setVisible(false);
+ }
+
+ private void initComponents() {
+ frame = new JFrame("๋ฉ์ผ ์ ์ก");
+ frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
+ frame.setSize(700, 450); // ์ฐฝ ํฌ๊ธฐ ์ค์
+ frame.setLocationRelativeTo(null); // Center the frame
+
+ recipientField = new JTextField(15);
+ subjectField = new JTextField(15);
+ messageArea = new JTextArea(10, 25);
+ sendButton = new JButton("Send");
+ attachButton = new JButton("Attach File");
+ quitButton = new JButton("QUIT");
+ fileField = new JTextField(15);
+ fileField.setEditable(false);
+ statusLabel = new JLabel();
+ errorLabel = new JLabel();
+ errorLabel.setForeground(Color.RED); // Set error message color
+
+ // Set colors for the components
+
+ recipientField.setForeground(new Color(56, 62, 88));
+ recipientField.setBackground(new Color(179, 182, 197));
+ subjectField.setForeground(new Color(56, 62, 88));
+ subjectField.setBackground(new Color(179, 182, 197));
+ messageArea.setForeground(new Color(56, 62, 88));
+ messageArea.setBackground(new Color(179, 182, 197));
+ fileField.setForeground(new Color(56, 62, 88));
+ fileField.setBackground(new Color(179, 182, 197));
+
+ recipientField.setForeground(Color.WHITE);
+ subjectField.setForeground(Color.WHITE);
+ messageArea.setForeground(Color.WHITE);
+ fileField.setForeground(Color.WHITE);
+
+
+ attachButton.setBackground(new Color(204, 122, 136)); // ๋ฐฐ๊ฒฝ์ ์ง์
+ attachButton.setForeground(Color.WHITE);
+ sendButton.setBackground(new Color(204, 122, 136)); // ๋ฐฐ๊ฒฝ์ ์ง์
+ sendButton.setForeground(Color.WHITE); // White text
+ quitButton.setBackground(new Color(225, 188, 181)); // ๋ฐฐ๊ฒฝ์ ์ง์
+ quitButton.setForeground(new Color(56, 62, 88)); // ๊ธ์ ์ ์ง์
+
+ sendButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ onSendButtonClick();
+ }
+ });
+
+ attachButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ onAttachButtonClick();
+ }
+ });
+
+ quitButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ onQuitButtonClick();
+ }
+ });
+
+ setLayout();
+ }
+
+ private void onSendButtonClick() {
+ String recipient = recipientField.getText();
+ String subject = subjectField.getText();
+ String message = messageArea.getText();
+ String[] recipients = recipient.split(",");
+ int maxRetries = 3; // ์ต๋ ์ฌ์๋ ํ์
+ int retryCount = 0;
+ boolean isSent = false;
+
+ if (recipient.isEmpty() || subject.isEmpty() || message.isEmpty()) {
+ showError("์ด๋ฉ์ผ ์ฃผ์, ์ ๋ชฉ, ๋ฉ์์ง๋ฅผ ๋ชจ๋ ์
๋ ฅํ์ธ์.");
+ return;
+ }
+
+ // ์ด๋ฉ์ผ ํ์ ์ ํจ์ฑ ๊ฒ์ฌ
+ if (!isValidEmailFormat(recipients)) {
+ showError("์ ํจํ ์ด๋ฉ์ผ ์ฃผ์๋ฅผ ์
๋ ฅํ์ธ์.");
+ return; // ์ ํจํ์ง ์์ ๊ฒฝ์ฐ ์ ์ก ์๋ํ์ง ์์
+ }
+
+ while (retryCount < maxRetries && !isSent) {
+ try {
+ EmailServiceWithNaver emailService = client.mailService;
+ if (emailService.isCorrectAddress()) {
+ emailService.connect();
+ for (String mailRec : recipients) {
+ if (attachedFile != null && attachedFile.exists()) {
+ File[] attachments = {attachedFile};
+ emailService.sendEmail(mailRec.trim(), subject, message, attachments); // ์ฒจ๋ถ ํ์ผ ์๋ ๊ฒฝ์ฐ
+ } else {
+ emailService.sendEmail(mailRec.trim(), subject, message, null); // ์ฒจ๋ถ ํ์ผ ์๋ ๊ฒฝ์ฐ
+ }
+ }
+ JOptionPane.showMessageDialog(frame, "์ด๋ฉ์ผ์ด ์ฑ๊ณต์ ์ผ๋ก ์ ์ก๋์์ต๋๋ค.", "์ ์ก ์๋ฃ", JOptionPane.INFORMATION_MESSAGE);
+ statusLabel.setText("์ด๋ฉ์ผ์ด ์ฑ๊ณต์ ์ผ๋ก ์ ์ก๋์์ต๋๋ค.");
+ clearFields();
+ isSent = true; // ์ ์ก ์ฑ๊ณต ์ true๋ก ์ค์
+ }
+
+ } catch (IOException e) {
+ retryCount++; // ์คํจ ์ ์ฌ์๋ ํ์ ์ฆ๊ฐ
+ showError("์ ์ก ์ค๋ฅ: " + e.getMessage() + " ์ฌ์๋ ์ค... (" + retryCount + "/" + maxRetries + ")");
+ }
+ }
+
+ if (!isSent) {
+ showError("์ด๋ฉ์ผ ์ ์ก ์คํจ: ์ต๋ ์ฌ์๋ ํ์๋ฅผ ์ด๊ณผํ์ต๋๋ค.");
+ }
+ }
+
+ // ์ด๋ฉ์ผ ํ์ ์ ํจ์ฑ ๊ฒ์ฌ ๋ฉ์๋
+ private boolean isValidEmailFormat(String[] emails) {
+ String emailRegex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+$"; // ์ด๋ฉ์ผ ํ์ ์ ๊ท์
+ for (String email : emails) {
+ if (!email.trim().matches(emailRegex))
+ return false; // ์ด๋ฉ์ผ ํ์์ด ์ ํจํ์ง ์์ผ๋ฉด false ๋ฐํ
+
+ // Show success message
+ JOptionPane.showMessageDialog(frame, "์ด๋ฉ์ผ์ด ์ฑ๊ณต์ ์ผ๋ก ์ ์ก๋์์ต๋๋ค.", "์ ์ก ์๋ฃ", JOptionPane.INFORMATION_MESSAGE);
+ statusLabel.setText("์ด๋ฉ์ผ์ด ์ฑ๊ณต์ ์ผ๋ก ์ ์ก๋์์ต๋๋ค.");
+ clearFields();
+
+
+ }
+ return true;
+ }
+
+
+ private void onAttachButtonClick() {
+ JFileChooser fileChooser = new JFileChooser();
+ int result = fileChooser.showOpenDialog(frame);
+
+ if (result == JFileChooser.APPROVE_OPTION) {
+ File selectedFile = fileChooser.getSelectedFile();
+ if (fileHandler.isValidFileType(selectedFile)) {
+ attachedFile = selectedFile;
+ fileField.setText(attachedFile.getAbsolutePath());
+ statusLabel.setText("์ฒจ๋ถ ํ์ผ: " + attachedFile.getName());
+ } else {
+ showError("์ ํจํ์ง ์์ ํ์ผ ํ์์
๋๋ค.");
+ }
+ }
+ }
+
+ private void onQuitButtonClick() {
+ try {
+ EmailServiceWithNaver emailService = client.mailService;
+
+ stopNoopScheduler();
+ // ์๋ฒ์ QUIT ๋ช
๋ น์ ๋ณด๋ด๊ณ ์ฐ๊ฒฐ ์ข
๋ฃ
+ emailService.Quit();
+
+ // ์ข
๋ฃ ๋ฉ์์ง ํ์
+ JOptionPane.showMessageDialog(frame, "์ฐ๊ฒฐ์ด ์ข
๋ฃ๋์์ต๋๋ค.", "์ข
๋ฃ", JOptionPane.INFORMATION_MESSAGE);
+
+ // ํ๋ก๊ทธ๋จ ์ข
๋ฃ
+ frame.dispose();
+ } catch (IOException e) {
+ showError("์ฐ๊ฒฐ ์ข
๋ฃ ์ค๋ฅ: " + e.getMessage());
+ }
+ }
+
+
+ // ์ฃผ๊ธฐ์ ์ผ๋ก NOOP ๋ช
๋ น์ ๋ณด๋ด๊ธฐ ์ํ ์ค์ผ์ค๋ฌ ์ค์
+ private void startNoopScheduler() {
+ if (noopScheduler != null && !noopScheduler.isShutdown()) {
+ System.out.println("NOOP ์ค์ผ์ค๋ฌ๊ฐ ์ด๋ฏธ ์คํ ์ค์
๋๋ค.");
+ return;
+ }
+ noopScheduler = Executors.newSingleThreadScheduledExecutor();
+ noopScheduler.scheduleAtFixedRate(() -> {
+ try {
+ client.mailService.sendNoop(); // NOOP ๋ช
๋ น ์ ์ก
+ System.out.println("NOOP ๋ช
๋ น์ด ์ ์ก๋์์ต๋๋ค.");
+ } catch (IOException e) {
+ showError("NOOP ๋ช
๋ น ์ ์ก ์ค๋ฅ: " + e.getMessage());
+ stopNoopScheduler(); // ์ค๋ฅ ๋ฐ์ ์ ์ค์ผ์ค๋ฌ ์ค์ง
+ unDisplay();
+ loginGUI.display();
+ }
+ }, 0, 9, TimeUnit.SECONDS); // 9์ด๋ง๋ค NOOP ์ ์ก
+ }
+
+
+ // ์ค์ผ์ค๋ฌ ์ค์ง
+ private void stopNoopScheduler() {
+ if (noopScheduler != null && !noopScheduler.isShutdown()) {
+ noopScheduler.shutdown();
+ }
+ }
+
+ private void showError(String message) {
+ errorLabel.setText(message);
+ JOptionPane.showMessageDialog(frame, message, "์ค๋ฅ", JOptionPane.ERROR_MESSAGE);
+ }
+
+ private void clearFields() {
+ recipientField.setText("");
+ subjectField.setText("");
+ messageArea.setText("");
+ fileField.setText("");
+ statusLabel.setText("");
+ errorLabel.setText("");
+ attachedFile = null; // Reset attached file
+ }
+
+ private void setLayout() {
+ JPanel panel = new JPanel();
+ frame.add(panel);
+ panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
+ panel.setBackground(new Color(56,62,88)); // ๋ฐฐ๊ฒฝ ์ ์ค์
+ panel.setBorder(new EmptyBorder(40,50,10,50));
+
+
+ JLabel toLabel = new JLabel("To.");
+ Font currentFont = toLabel.getFont();
+ toLabel.setFont(currentFont.deriveFont(Font.BOLD,13f)); // ํฌ๊ธฐ๋ฅผ 13์ผ๋ก ์ค์
+ toLabel.setForeground(Color.white); // ๊ธ์จ ์์ ์ค์
+ toLabel.setAlignmentX(JLabel.LEFT_ALIGNMENT); // ์ผ์ชฝ ์ ๋ ฌ
+ panel.add(toLabel);
+ panel.add(Box.createRigidArea(new Dimension(0, 5))); // ์ฌ๋ฐฑ
+
+ panel.add(recipientField);
+ panel.add(Box.createRigidArea(new Dimension(0, 9))); // ์ฌ๋ฐฑ
+
+ JLabel subjectLabel = new JLabel("Subject.");
+ subjectLabel.setFont(currentFont.deriveFont(Font.BOLD,13f)); // ํฌ๊ธฐ๋ฅผ 13์ผ๋ก ์ค์
+ subjectLabel.setForeground(Color.white); // ๊ธ์จ ์์ ์ค์
+ subjectLabel.setHorizontalAlignment(SwingConstants.LEFT); // ์ผ์ชฝ ์ ๋ ฌ
+ panel.add(subjectLabel);
+ panel.add(Box.createRigidArea(new Dimension(0, 5))); // ์ฌ๋ฐฑ
+
+ panel.add(subjectField);
+ panel.add(Box.createRigidArea(new Dimension(0, 9))); // ์ฌ๋ฐฑ
+
+ JLabel messageLabel = new JLabel("Message.");
+ messageLabel.setFont(currentFont.deriveFont(Font.BOLD,13f)); // ํฌ๊ธฐ๋ฅผ 13์ผ๋ก ์ค์
+ messageLabel.setForeground(Color.white); // ๊ธ์จ ์์ ์ค์
+ panel.add(messageLabel);
+ panel.add(Box.createRigidArea(new Dimension(0, 5))); // ์ฌ๋ฐฑ
+
+ panel.add(new JScrollPane(messageArea));
+
+ panel.add(Box.createRigidArea(new Dimension(0, 9)));
+
+ panel.add(attachButton); // ํ์ผ ์ฒจ๋ถ ๋ฒํผ
+
+ panel.add(Box.createRigidArea(new Dimension(0, 9))); // ์ฌ๋ฐฑ ์ถ๊ฐ
+
+ panel.add(fileField);
+
+ panel.add(Box.createRigidArea(new Dimension(0, 10))); // ์ฌ๋ฐฑ ์ถ๊ฐ
+
+ panel.add(statusLabel);
+ panel.add(errorLabel);
+
+ // ๋ฒํผ ํจ๋ ์์ฑ ๋ฐ FlowLayout ์ค์
+ JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); // ๋ฒํผ ํจ๋ ์์ฑ
+ buttonPanel.setBackground(new Color(56,62,88)); // ๋ฐฐ๊ฒฝ ์ ์ค์
+ buttonPanel.add(sendButton); // sendButton ์ถ๊ฐ
+ buttonPanel.add(quitButton); // quitButton ์ถ๊ฐ
+ buttonPanel.setAlignmentX(JPanel.LEFT_ALIGNMENT); // ์ผ์ชฝ ์ ๋ ฌ
+
+ panel.add(buttonPanel); // ๋ฒํผ ํจ๋์ ๋ฉ์ธ ํจ๋์ ์ถ๊ฐ
+
+
+ }
+ }
+ ```
+
+
+ - ์ด๋ฉ์ผ ์์ฑ ๋ฐ ์ ์กํ๋ GUI ์ ๊ณต, ์ฒจ๋ถ ํ์ผ ๊ธฐ๋ฅ, ์ฃผ๊ธฐ์ ์ธ ์๋ฒ ์ฐ๊ฒฐ ์ ์ง ๊ธฐ๋ฅ
+
+ - `SendEmailGUI`
+ - Client์ LoginGUI ์ธ์คํด์ค๋ฅผ ๋ฐ์์ ์ด๋ฉ์ผ ์ ์ก์ ์ฌ์ฉ, LoginGUI๋ฅผ ํตํด ์ฌ๋ก๊ทธ์ธ์ ์ง์
+ - `initComponents()` ํธ์ถ โ ๋ชจ๋ component ์ด๊ธฐํ
+ - `startNoopScheduler()` โ ์๋ฒ ์ฐ๊ฒฐ์ ์ ์งํ๊ธฐ ์ํ NOOP ๋ช
๋ น์ 9์ด ๊ฐ๊ฒฉ์ผ๋ก ์ ์ก
+ - `button`
+ - `onSendButtonClick()`: ์์ ์, ์ ๋ชฉ, ๋ฉ์์ง ํ์ธ โ SMTP ์๋ฒ์ ์ฐ๊ฒฐํ์ฌ ์ด๋ฉ์ผ ์ ์ก (์ ์ก ์คํจ ์ ์ต๋ 3๋ฒ๊น์ง ์ฌ์๋ ๊ฐ๋ฅ)
+ - `onAttachButtonClick()`: `JFileChooser`์ ํตํด ํ์ผ ์ ํ โ `fileHandler.isValidFileType()`๋ก ํ์ผ ํ์ ๊ฒ์ฌ โ ์ ํจํ ํ์ผ์ด๋ฉด `attachedFile`์ ์ ์ฅ
+ - `onQuitButtonClick()`: ์๋ฒ ์ฐ๊ฒฐ ์ข
๋ฃ, NOOP ์ค์ผ์ค๋ฌ ์ค์ง, ์ฐฝ ๋ซ์ ํ `LoginGUI` ์ฐฝ ํ์
-
- MimeMessageBuilder.java
-
- ```javascript
- package email.mime;
-
-import javax.mail.*; // javax.mail ํจํค์ง์์ ํ์ํ ํด๋์ค๋ค์ ์ํฌํธ
-import javax.mail.internet.*; // ์ด๋ฉ์ผ ์ ์ก์ ์ํ ์ธํฐ๋ท ๋ฉ์ผ ํด๋์ค๋ฅผ ์ํฌํธ
-import java.util.Properties; // ์ด๋ฉ์ผ ์ ์ก์ ํ์ํ ์ค์ ์ ๋ณด๋ฅผ ์ ์ฅํ๊ธฐ ์ํ ํด๋์ค
-
-public class MimeMessageBuilder {
- private Session session; // ๋ฉ์ผ ์ธ์
์ ์ํ ๊ฐ์ฒด
- private MimeMessage message; // MIME ๋ฉ์์ง๋ฅผ ์ํ ๊ฐ์ฒด
-
- // MimeMessageBuilder ์์ฑ์
- // ์ด๋ฉ์ผ ์ธ์
์ ์ด๊ธฐํํ๊ณ ๋ฉ์์ง ๊ฐ์ฒด๋ฅผ ์์ฑ
- public MimeMessageBuilder(String smtpHost, String smtpPort, String email, String password) {
- Properties properties = new Properties(); // ๋ฉ์ผ ์๋ฒ ์ฐ๊ฒฐ์ ์ํ ์ค์
- properties.put("mail.smtp.host", smtpHost); // SMTP ์๋ฒ ํธ์คํธ ์ค์
- properties.put("mail.smtp.port", smtpPort); // SMTP ์๋ฒ ํฌํธ ์ค์
- properties.put("mail.smtp.auth", "true"); // SMTP ์ธ์ฆ ์ฌ์ฉ ์ค์
- properties.put("mail.smtp.starttls.enable", "true"); // TLS ์ฌ์ฉ ์ค์
-
- session = Session.getInstance(properties, new Authenticator() {
- @Override
- protected PasswordAuthentication getPasswordAuthentication() {
- return new PasswordAuthentication(email, password); // ์ด๋ฉ์ผ๊ณผ ๋น๋ฐ๋ฒํธ๋ก ์ธ์ฆ
- }
- });
-
- try {
- message = new MimeMessage(session); // ์ธ์
์ ์ฌ์ฉํ์ฌ MIME ๋ฉ์์ง ์์ฑ
- } catch (MessagingException e) {
- e.printStackTrace(); // ๋ฉ์์ง ์์ฑ ์ ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ์ถ๋ ฅ
- }
- }
-
- // ์์ ์ ์ด๋ฉ์ผ ์ฃผ์ ์ค์ ๋ฉ์๋
- // ์์ ์์ ์ด๋ฉ์ผ ์ฃผ์๋ฅผ ์ถ๊ฐ
- public void setRecipient(String recipient) throws MessagingException {
- message.addRecipient(Message.RecipientType.TO, new InternetAddress(recipient)); // ์์ ์ ์ถ๊ฐ
- }
-
- // ์ด๋ฉ์ผ ์ ๋ชฉ ์ค์ ๋ฉ์๋
- // ์ด๋ฉ์ผ ์ ๋ชฉ์ ์ค์
- public void setSubject(String subject) throws MessagingException {
- message.setSubject(subject); // ์ ๋ชฉ ์ค์
- }
-
- // ์ด๋ฉ์ผ ๋ณธ๋ฌธ ์ค์ ๋ฉ์๋
- // ์ด๋ฉ์ผ ๋ด์ฉ์ ์ค์ (HTML ํ์ ์ง์)
- public void setBody(String body) throws MessagingException {
- message.setContent(body, "text/html; charset=utf-8"); // ๋ณธ๋ฌธ ๋ด์ฉ ์ค์
- }
-
- // ์ด๋ฉ์ผ ์ฒจ๋ถ ํ์ผ ์ถ๊ฐ ๋ฉ์๋
- // ์ฒจ๋ถํ ํ์ผ ๊ฒฝ๋ก๋ฅผ ๋ฐ์ MIME ๋ฉ์์ง์ ์ฒจ๋ถ
- public void addAttachment(String filePath) throws MessagingException {
- MimeBodyPart messageBodyPart = new MimeBodyPart(); // ์ฒจ๋ถ ํ์ผ์ ์ํ ๋ฐ๋ ํํธ ์์ฑ
- messageBodyPart.setFileName(filePath); // ํ์ผ ์ด๋ฆ ์ค์
-
- MimeMultipart multipart = new MimeMultipart(); // ์ฌ๋ฌ ๋ถ๋ถ์ผ๋ก ๊ตฌ์ฑ๋ MIME ๋ฉ์์ง ์์ฑ
- multipart.addBodyPart(messageBodyPart); // ๋ฐ๋ ํํธ ์ถ๊ฐ
- message.setContent(multipart); // ๋ฉ์์ง์ MIME ๋ฉํฐํํธ ์ค์
- }
+
+### 2. *email.mime*
+- **FileHandler.java**
+
+ FileHandler.java
+
+ ```javascript
+ package email.mime;
+
+ import java.io.*;
+ import java.nio.file.Files;
+ import java.nio.file.Path;
+ import java.nio.file.Paths;
+ import java.nio.file.StandardCopyOption;
+ public class FileHandler {
+
+ public void attachFile(String filePath) {
+ File file = new File(filePath);
+ if (file.exists()) {
+ if (isValidFileType(file)) {
+ System.out.println(file.getName() + " ํ์ผ์ด ์ฒจ๋ถ๋์์ต๋๋ค.");
+ } else {
+ System.out.println("์ ํจํ์ง ์์ ํ์ผ์
๋๋ค.");
+ }
+ } else {
+ System.out.println("ํ์ผ์ด ์กด์ฌํ์ง ์์ต๋๋ค.");
+ }
+ }
+
+ public String getMimeType(String filePath) {
+ Path path = Paths.get(filePath);
+ try {
+ return Files.probeContentType(path);
+ } catch (IOException e) {
+ System.err.println("MIME ํ์
ํ์ง ์ค๋ฅ: " + e.getMessage());
+ return "์ ์ ์๋ MIME ํ์
";
+ }
+ }
+
+ public boolean isValidFileType(File file) {
+ String mimeType = getMimeType(file.getAbsolutePath());
+ return mimeType.startsWith("image") || mimeType.equals("application/pdf") || mimeType.startsWith("text");
+ }
+
+ public long getFileSize(String filePath) {
+ File file = new File(filePath);
+ if (file.exists()) {
+ return file.length();
+ } else {
+ System.out.println("ํ์ผ์ ์ฐพ์ ์ ์์ต๋๋ค.");
+ return 0;
+ }
+ }
+
+ public void saveFileToDisk(File file, String destinationDirectory) {
+ Path destinationPath = Paths.get(destinationDirectory, file.getName());
+ try {
+ Files.copy(file.toPath(), destinationPath, StandardCopyOption.REPLACE_EXISTING);
+ } catch (IOException e) {
+ System.err.println("ํ์ผ ์ ์ฅ ์ค๋ฅ: " + e.getMessage());
+ }
+ }
+
+ public String readFile(String filePath) {
+ StringBuilder contentBuilder = new StringBuilder();
+ try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
+ String line;
+ while ((line = br.readLine()) != null) {
+ contentBuilder.append(line).append(System.lineSeparator());
+ }
+ } catch (IOException e) {
+ System.err.println("ํ์ผ ์ฝ๊ธฐ ์ค๋ฅ: " + e.getMessage());
+ }
+ return contentBuilder.toString();
+ }
+ }
+ ```
+
+
+ - ํ์ผ ์ฒจ๋ถ, MIME ํ์
ํ์ธ, ํ์ผ ํฌ๊ธฐ ์ธก์ , ํ์ผ ์ ์ฅ, ํ์ผ ์ฝ๊ธฐ ๊ธฐ๋ฅ
+
+ - `attachFile`
+ - ์ง์ ํ์ผ๊ฒฝ๋ก์ ํ์ผ์ด ์กด์ฌํ๋์ง ํ์ธ, ์ ํจํ ํ์ผ ํ์์ธ์ง ๊ฒ์ฌ
+ - ์ ํจํ ํ์์ ํ์ผ: ํ์ผ์ด ์ฒจ๋ถ๋์๋ค๋ ๋ฉ์์ง ์ถ๋ ฅ
+ - ์ ํจํ์ง ์์ ํ์์ ํ์ผ: "์ ํจํ์ง ์์ ํ์ผ์
๋๋ค" ๋ฉ์์ง ์ถ๋ ฅ
+ - `getMimeType`
+ - `Files.probeContentType()` ํตํด ํ์ผ ๊ฒฝ๋ก๋ก๋ถํฐ MIME ํ์
์ถ์ถ
+ - ์์ธ๊ฐ ๋ฐ์ํ ๊ฒฝ์ฐ "์ ์ ์๋ MIME ํ์
" ๋ฐํ
+ - `isValidFileType`
+ - MIME ํ์
์ด ์ด๋ฏธ์ง, PDF, ํ
์คํธ ํ์ผ์ธ์ง ํ์ธ โ ์ ํจ์ฑ์ ๊ฒ์ฌ
+ - ์ ํจํ ํ์: true ๋ฐํ
+ - ์ ํจํ์ง ์์ ํ์: false ๋ฐํ
+ - `getFileSize`
+ - ์ง์ ๋ ํ์ผ์ ํฌ๊ธฐ๋ฅผ ๋ฐ์ดํธ ๋จ์๋ก ๋ฐํ
+ - ํ์ผ์ด ์กด์ฌํ์ง ์์ผ๋ฉด 0 ๋ฐํ, "ํ์ผ์ ์ฐพ์ ์ ์์ต๋๋ค" ๋ฉ์์ง ์ถ๋ ฅ
+ - `saveFileToDisk`
+ - ํ์ผ์ ์ง์ ๋ ๋๋ ํ ๋ฆฌ๋ก ๋ณต์ฌํ์ฌ ์ ์ฅ
+ - ๋์ผํ ์ด๋ฆ์ ํ์ผ์ด ์์ ๊ฒฝ์ฐ: `StandardCopyOption.REPLACE_EXISTING`์ ์ฌ์ฉํด ๊ธฐ์กด ํ์ผ์ ๋ฎ์
+ - `readFile`
+ - `BufferedReader`๋ก ํ์ผ์ ํ ์ค์ฉ ์ฝ๊ธฐ โ `StringBuilder`์ ๋ด์ฉ ์ ์ฅ โ ๋ง์ง๋ง์ ๋ฐํ
- // MIME ๋ฉ์์ง ์ ์ก ๋ฉ์๋
- // ์์ฑ๋ ๋ฉ์์ง๋ฅผ ์ ์ก
- public void send() throws MessagingException {
- Transport.send(message); // ์ด๋ฉ์ผ ์ ์ก
- System.out.println("์ด๋ฉ์ผ์ด ์ ์ก๋์์ต๋๋ค."); // ์ ์ก ์ฑ๊ณต ๋ฉ์์ง ์ถ๋ ฅ
- }
-}
- ```
-
+
+- **MimeMessageBuilder.java**
+
+ MimeMessageBuilder.java
+
+ ```javascript
+ package email.mime;
+
+ import java.io.*;
+ import java.nio.file.Files;
+ import java.util.Base64;
+
+ public class MimeMessageBuilder {
+ private String boundary;
+ private String from;
+ private String to;
+ private String subject;
+ private String body;
+ private File[] attachments;
+
+ public MimeMessageBuilder(String from, String to, String subject, String body, File[] attachments) {
+ this.from = from;
+ this.to = to;
+ this.subject = subject;
+ this.body = body;
+ this.attachments = attachments;
+ this.boundary = "----=_MIME_BOUNDARY_" + System.currentTimeMillis();
+ }
+
+ // From ํค๋
+ private String createFromHeader() {
+ return "From: " + from + "\r\n";
+ }
+
+ // To ํค๋
+ private String createToHeader() {
+ return "To: " + to + "\r\n";
+ }
+
+ // Subject ํค๋
+ private String createSubjectHeader() {
+ return "Subject: " + subject + "\r\n";
+ }
+
+ // MIME ๋ณธ๋ฌธ
+ private String createMimeBody() {
+ StringBuilder mimeBody = new StringBuilder();
+ mimeBody.append("Content-Type: text/plain; charset=UTF-8\r\n");
+ mimeBody.append("Content-Transfer-Encoding: 7bit\r\n");
+ mimeBody.append("\r\n");
+ mimeBody.append(body).append("\r\n");
+ return mimeBody.toString();
+ }
+
+ // ์ฒจ๋ถ ํ์ผ์ MIME ํํธ๋ก ์ธ์ฝ๋ฉ
+ private String createMimeAttachment(File file) throws IOException {
+ StringBuilder mimeAttachment = new StringBuilder();
+ mimeAttachment.append("Content-Type: application/octet-stream; name=\"").append(file.getName()).append("\"\r\n");
+ mimeAttachment.append("Content-Transfer-Encoding: base64\r\n");
+ mimeAttachment.append("Content-Disposition: attachment; filename=\"").append(file.getName()).append("\"\r\n");
+ mimeAttachment.append("\r\n");
+ mimeAttachment.append(encodeFileToBase64(file)).append("\r\n");
+ return mimeAttachment.toString();
+ }
+
+ // Boundary ์ถ๊ฐ
+ private String createMimeBoundary() {
+ return "--" + boundary + "\r\n";
+ }
+
+ // Base64 ์ธ์ฝ๋ฉ
+ private String encodeFileToBase64(File file) throws IOException {
+ byte[] fileContent = Files.readAllBytes(file.toPath());
+ return Base64.getEncoder().encodeToString(fileContent);
+ }
+
+ // ์ต์ข
MIME ๋ฉ์์ง ์์ฑ
+ public String build() throws IOException {
+ StringBuilder mimeMessage = new StringBuilder();
+
+ mimeMessage.append(createFromHeader());
+ mimeMessage.append(createToHeader());
+ mimeMessage.append(createSubjectHeader());
+ mimeMessage.append("MIME-Version: 1.0\r\n");
+ mimeMessage.append("Content-Type: multipart/mixed; boundary=\"").append(boundary).append("\"\r\n");
+ mimeMessage.append("\r\n");
+
+ // ๋ณธ๋ฌธ ์ถ๊ฐ
+ mimeMessage.append(createMimeBoundary());
+ mimeMessage.append(createMimeBody());
+
+ // ์ฒจ๋ถ ํ์ผ ์ถ๊ฐ
+ if (attachments != null) {
+ for (File file : attachments) {
+ mimeMessage.append(createMimeBoundary());
+ mimeMessage.append(createMimeAttachment(file));
+ }
+ }
+
+ // ๋ฉ์์ง ์ข
๋ฃ
+ mimeMessage.append("--").append(boundary).append("--\r\n");
+
+ return mimeMessage.toString();
+ }
+ }
+ ```
+
+
+ - ํค๋ ์์ฑ, ์ด๋ฉ์ผ ๋ณธ๋ฌธ๊ณผ ์ฒจ๋ถ ํ์ผ์ MIME ํ์์ผ๋ก ๊ตฌ์ฑ, ์์ฑ๋ MIME ๋ฉ์์ง๋ฅผ ๋ฌธ์์ด ํํ๋ก ๋ฐํ
+
+ - `createFromHeader()` `createToHeader()` `createSubjectHeader()`
+ - ๊ฐ๊ฐ ๋ฐ์ ์, ์์ ์, ์ ๋ชฉ ํ๋์ ํค๋ ์์ฑ
+ - `createMimeBody`
+ - ์ด๋ฉ์ผ ๋ณธ๋ฌธ์ MIME ํ์์ผ๋ก ์์ฑ
+ - ๋ณธ๋ฌธ์ ํ
์คํธ๋ก ์ค์ , `text/plain` `charset`์ UTF-8๋ก ์ง์
+ - `createMimeAttachment`
+ - ์ฒจ๋ถ ํ์ผ์ base64๋ก ์ธ์ฝ๋ฉํ์ฌ MIME ํ์์ผ๋ก ๊ตฌ์ฑ
+ - `Content-Transfer-Encoding: base64`: ์ฒจ๋ถ ํ์ผ ๋ด์ฉ์ Base64๋ก ์ธ์ฝ๋ฉ
+ - `encodeFileToBase64`
+ - ์ฒจ๋ถ ํ์ผ ๋ฐ์ดํธ ๋ฐ์ดํฐ๋ฅผ Base64๋ก ์ธ์ฝ๋ฉํ์ฌ ๋ฐํ
+ - SMTP๋ก ์ ์กํ ์ ์๋๋ก ASCII ๋ฌธ์์ด ํ์์ผ๋ก ๋ณํ
+ - `build`
+ - `createMimeBoundary()`: ๋ณธ๋ฌธ๊ณผ ์ฒจ๋ถ ํ์ผ ๊ตฌ๋ถ
+ - ์ฒจ๋ถ ํ์ผ์ด ์์ ๊ฒฝ์ฐ ์ด๋ฅผ MIME ํํธ๋ก ์ถ๊ฐ
-- `FileHandler.java`: ํ์ผ ์ฒจ๋ถ ์ฒ๋ฆฌ ๋ฐ ํ์ผ ๊ด๋ จ ์์
-- `MimeMessageBuilder.java`: MIME ๋ฉ์์ง ์์ฑ ๋ฐ ๊ด๋ จ ์ฒ๋ฆฌ
+
+### 3. *email.smtp*
-### 3. `email.smtp`
-
- Auth.java
-
-```javascript
-
-```
-
-
-
- Client.java
-
-```javascript
-package email.smtp;
-
-import java.io.*;
-import java.net.Socket;
-import java.util.Base64;
-import email.mime.FileHandler;
-import email.smtp.Auth;
-
-public class Client {
- private Auth auth; // ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด
- private FileHandler fileHandler; // ํ์ผ ์ฒ๋ฆฌ
-
- // Client ์์ฑ์
- public Client(Auth auth, FileHandler fileHandler) {
- this.auth = auth; // ์ธ์ฆ ๊ฐ์ฒด ์ค์
- this.fileHandler = fileHandler; // ํ์ผ ์ฒ๋ฆฌ ๊ฐ์ฒด ์ค์
+- **Client.java**
+
+ Client.java
+
+ ```javascript
+ package email.smtp;
+
+ public class Client {
+
+ public EmailServiceWithNaver mailService;
+
+ public Client(String mail, String password) {
+ if (mail.endsWith("@naver.com")) {
+ mailService=new EmailServiceWithNaver(mail,password,"smtp.naver.com",465);
+
+ }else
+ mailService=new EmailServiceWithNaver(mail,password,null,-1);
+ }
}
+
+ ```
+
+
+ * ์ฌ์ฉ์์๊ฒ ์ด๋ฉ์ผ ์ฃผ์์ ๋น๋ฐ๋ฒํธ๋ฅผ ๋ฐ์ ํด๋น ์ด๋ฉ์ผ ์๋น์ค์ ๋ง๋ `EmailServiceWithNaver` ๊ฐ์ฒด ์ด๊ธฐํ
- // ์ด๋ฉ์ผ ์ ์ก ๋ฉ์๋
- // ์ด๋ฉ์ผ ์์ฑํ ๋ด์ฉ์ ๋ฐ์์์ ์ ์กํ๋ ๋ฉ์๋ ์
๋๋ค.
- // Auth class ์ฐธ๊ณ ํ๋ฉด์ ์์ฑํ๋๋ฐ private ๋ณ์๋ฅผ public์ผ๋ก ๋ฐ๊พธ์ ์ฌ์ฉํ์ต๋๋ค..
- public boolean sendEmail(String recipient, String subject, String messageBody, String filePath) {
- // ์ง์ํ๋ ์ด๋ฉ์ผ ํ์์ธ์ง ๊ตฌ๋ถ
- if (!auth.authenticate()) { // ์ธ์ฆ ๋์ง ์์์ผ๋ฉด false ๋ฐํ
- return false;
- }
-
- // ์์ผ ์ค์
- try (Socket socket = new Socket(auth.smtpServer, auth.port); // SMTP ์๋ฒ์ ์์ผ ์ฐ๊ฒฐ
- BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); // ์๋ฒ ์๋ต ์ฝ๊ธฐ
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()))) { // ์๋ฒ์
- // ๋ช
๋ น์ด
- // ์ฐ๊ธฐ
-
- // ์๋ฒ ์๋ต ํ์ธ
- readResponse(reader);
-
- // EHLO ๋ช
๋ น - SMTP ์๋ฒ ํต์ ์์
- sendCommand(writer, "EHLO " + auth.smtpServer);
- readResponse(reader);
-
- // SMTP ์ธ์ฆ
- sendCommand(writer, "AUTH LOGIN"); // ์ธ์ฆ ์์
- readResponse(reader);
-
- // ์ผ๋จ ์ด๋ฉ์ผ,๋น๋ฐ๋ฒํธ ์ธ์ฝ๋ฉ ์์ฑํ๊ธฐ๋ํ๋๋ฐ MIME ์ด๋ FileHandler ์์ ์ฒ๋ฆฌํด์ฃผ์๋ฉด ์ฝ๋ ๋ค์ ๋ฐ๊พธ๋ฉด ๋ ๋ฏํฉ๋๋ค.
- sendCommand(writer, Base64.getEncoder().encodeToString(auth.email.getBytes())); // ์ด๋ฉ์ผ ์ฃผ์ ์ธ์ฝ๋ฉ ์ ์ก
- readResponse(reader);
- sendCommand(writer, Base64.getEncoder().encodeToString(auth.password.getBytes())); // ๋น๋ฐ๋ฒํธ ์ธ์ฝ๋ฉ ์ ์ก
- readResponse(reader);
-
- // ์ก์ ์์ ์์ ์ ์ค์
- sendCommand(writer, "MAIL FROM:<" + auth.email + ">"); // ์ก์ ์ ์ค์
- readResponse(reader);
- sendCommand(writer, "RCPT TO:<" + recipient + ">"); // ์์ ์ ์ค์
- readResponse(reader);
-
- // ๋ฐ์ดํฐ ์ ์ก ์์
- sendCommand(writer, "DATA"); // ๋ฐ์ดํฐ ์ ์ก
- readResponse(reader);
+ * `mailService`
+ - `EmailServiceWithNaver`์ ์ธ์คํด์ค
+ - ์ค์ ์ด๋ฉ์ผ ์ ์ก ๋ฐ SMTP ์ฐ๊ฒฐ ๊ธฐ๋ฅ ์ํ
+
+ * `Client`
+ - mail์ด `@naver.com`์ผ๋ก ๋๋๋์ง ํ์ธ
+ - `@naver.com` ๋๋ฉ์ธ์ธ ๊ฒฝ์ฐ: `mailService`๊ฐ `smtp.naver.com` ์๋ฒ๋ก ์ฐ๊ฒฐ
+ - `@naver.com` ๋๋ฉ์ธ์ด ์๋ ๊ฒฝ์ฐ: `EmailServiceWithNaver` ์ธ์คํด์ค ์์ฑ, SMTP ์๋ฒ ์ ๋ณด `null`๊ณผ `-1`๋ก ์ค์ โ ์ฐ๊ฒฐ X
- // ์ด๋ฉ์ผ ๋ณธ๋ฌธ ์์ฑ
- writer.write("Subject: " + subject + "\r\n"); // ์ ๋ชฉ
- writer.write("From: " + auth.email + "\r\n"); // ์ก์ ์
- writer.write("To: " + recipient + "\r\n"); // ์์ ์
- writer.write("MIME-Version: 1.0\r\n"); // MIME ๋ฒ์ 1.0์ผ๋ก ์ค์
- writer.write("Content-Type: multipart/mixed; boundary=\"boundary\"\r\n"); // ์ด๋ฉ์ผ ๋ณธ๋ฌธ ์ ํ ๋ฉํฐํํธ(ํ
์คํธ+์ฒจ๋ถํ์ผ)์ผ๋ก ์ง์
- writer.write("\r\n--boundary\r\n"); // ๋ณธ๋ฌธ๊ณผ ์ฒจ๋ถ ํ์ผ ๊ตฌ๋ถ
- writer.write("Content-Type: text/plain; charset=UTF-8\r\n\r\n"); // ํ
์คํธ ํ์ ๋ช
์
- writer.write(messageBody + "\r\n"); // ๋ณธ๋ฌธ ๋ด์ฉ ์ถ๊ฐ
+- **EmailServiceWithNaver.java**
+
+ EmailServiceWithNaver.java
+
+ ```javascript
+ package email.smtp;
+
+ import email.mime.MimeMessageBuilder;
+
+ import java.io.*;
+ import java.net.*;
+ import java.util.Base64;
+ import java.util.ArrayList;
+ import java.util.List;
+ import javax.net.ssl.*;
+
+ public class EmailServiceWithNaver {
+ protected SSLSocketFactory factory;
+ protected SSLSocket socket;
+ protected PrintWriter out;
+ protected BufferedReader in;
+ protected String mail, password, smtpServer;
+ protected int port;
+
+ // List to store requests and responses
+ protected List responses;
+
+ public EmailServiceWithNaver(String mail, String password, String smtpServer, int port) {
+ this.mail = mail;
+ this.password = password;
+ this.smtpServer = smtpServer;
+ this.port = port;
+ this.responses = new ArrayList<>(); // Initialize response list
+ }
+
+ // Check if a valid domain name has been entered
+ public boolean isCorrectAddress() {
+ return port != -1;
+ }
+
+ public void connect() throws IOException {
+ System.out.println("Attempting to connect to SMTP server: " + smtpServer + " Port: " + port);
+
+ factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
+ socket = (SSLSocket) factory.createSocket(smtpServer, port);
+ in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
+ out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
+
+ // Start handshake
+ System.out.println("Starting handshake...");
+ socket.startHandshake(); // Start handshake
+
+ // Process server response and send commands
+ getSingleResponse(); // Read server response
+
+ // Send EHLO command
+ sendCommand("EHLO " + smtpServer);
+ get250Response();
+
+ // Send AUTH LOGIN command
+ sendCommand("AUTH LOGIN");
+ getSingleResponse();
+
+ // Send encoded email address
+ sendCommand(Base64.getEncoder().encodeToString(mail.getBytes("UTF-8")));
+
+ String authResponses = getSingleResponse();
+
+ // Check responses during authentication process
+
+ // Send encoded password
+ sendCommand(Base64.getEncoder().encodeToString(password.getBytes("UTF-8")));
+ authResponses = getSingleResponse();
+
+ // Check responses during authentication process
+ if (!checkResponse(authResponses)) {
+ throw new IOException("Authentication failed: Please enter a valid email/password.");
+ }
+ // Check final response
+ }
+
+ // Method to output requests and responses
+ protected void sendCommand(String command) throws IOException {
+ System.out.println("Client command: " + command);
+ out.println(command);
+ out.flush();
+ }
+
+ public void sendEmail(String to, String subject, String body,File[] attachments) throws IOException {
+ // Create and send message
+ MimeMessageBuilder builder = new MimeMessageBuilder(mail, to, subject, body, attachments);
+ String mimeMessage = builder.build();
+
+ sendCommand("MAIL FROM:<" + mail + ">");
+ String response = getSingleResponse();
+
+ sendCommand("RCPT TO:<" + to + ">");
+ response = getSingleResponse();
+ if (!checkResponse(response)) {
+ throw new IOException("An error occurred with the recipient's email address. Please check if it is correct.\n" + String.join(", ", response));
+ }
+
+ sendCommand("DATA");
+ response = getSingleResponse();
+ if (!checkResponse(response)) {
+ throw new IOException("An error occurred during the data transmission preparation.\n " + String.join(", ", response));
+ }
+
+ // Write and send email body
+
+ out.print(mimeMessage + "\r\n.\r\n");
+ out.flush();
+ response = getSingleResponse();
+
+ if (!checkResponse(response)) {
+ throw new IOException("An error occurred while sending the email body.\n " + String.join(", ", response));
+ }
+ }
+ public void Quit() throws IOException {
+ // Send QUIT command
+ System.out.println("Sending QUIT command");
+ out.println("QUIT");
+ out.flush();
+ String response = getSingleResponse();
+ if (!checkResponse(response)) {
+ throw new IOException("An error occurred during the connection termination process.\n " + String.join(", ", response));
+ }
+ // Close socket
+ socket.close();
+ out.close();
+ in.close();
+ System.out.println("Email sent and connection terminated");
+ }
+
+ public void sendNoop() throws IOException {
+ // NOOP ๋ช
๋ น ๋ณด๋ด๊ธฐ
+ sendCommand("NOOP");
+
+ // ์๋ฒ ์๋ต ์ฝ์
+ String response = getSingleResponse();
+
+ // ์๋ต์ฑ๊ณตํ๋์ง ํ์ธ (2xx or 3xx)
+ if (checkResponse(response)) {
+ System.out.println("NOOP ๋ช
๋ น ์ฑ๊ณต, ์ฐ๊ฒฐ ์ ์ง๋จ.");
+ } else {
+ throw new IOException("์ฐ๊ฒฐ ์ ์ง์ ์คํจ ํจ. ์๋ฒ ์๋ต: " + response);
+ }
+ }
+
+ // Read server response
+ public String[] get250Response() throws IOException {
+ ArrayList responses = new ArrayList<>(); // ArrayList to store responses
+ String response;
+
+ // Read multiple lines of responses
+ while ((response = getSingleResponse()) != null) {
+ responses.add(response); // Add response
+ if (!response.startsWith("250-")) { // Stop loop if not starting with 250
+ break;
+ }
+ }
+
+ return responses.toArray(new String[0]); // Convert ArrayList to array and return
+ }
+
+ public String getSingleResponse() throws IOException {
+ String response = in.readLine(); // Read a single line
+ if (response != null) {
+ System.out.println(response); // Print the response
+ }
+ return response; // Return the response
+ }
+
+ // Check an array of responses
+
+ // Check a single response
+ public boolean checkResponse(String reply) throws NullPointerException {
+ return reply.startsWith("2") || reply.startsWith("3");
+ }
+
+
+ // Email address validation
+ @Override
+ public String toString() {
+ return "Server: " + smtpServer + ", Mail ID: " + mail;
+ }
+ }
+ ```
+
+
+ - ๋ค์ด๋ฒ SMTP ์๋ฒ์ ์์ ํ ์ฐ๊ฒฐ์ ๊ตฌ์ถํ๊ณ , ์ด๋ฉ์ผ ์ธ์ฆ๊ณผ ๋ฐ์ดํฐ ์ ์ก์ ์ํ
+
+ - `isCorrectAddress`
+ - ํฌํธ๊ฐ `-1`์ด ์๋ ๊ฒฝ์ฐ ์ ํจํ ์ด๋ฉ์ผ ์ฃผ์๋ก ๊ฐ์ฃผ, ๊ทธ๋ ์ง ์์ผ๋ฉด ์ ํจํ์ง ์์ ์ฃผ์๋ก ๊ฐ์ฃผ
+ - `connect`
+ - SMTP ์๋ฒ์ SSL์ ์ฌ์ฉํ์ฌ ์ฐ๊ฒฐ ์ค์ , ๊ธฐ๋ณธ ์ธ์ฆ ์ํ
+ - EHLO ๋ช
๋ น โ ์๋ฒ์ ํต์ ์์
+ - AUTH LOGIN ๋ช
๋ น โ ์ธ์ฆ ๊ณผ์ ์งํ
+ - ์ด๋ฉ์ผ ์ฃผ์์ ๋น๋ฐ๋ฒํธ๋ฅผ Base64๋ก ์ธ์ฝ๋ฉํ์ฌ ์ ์ก
+ - `sendEmail`
+ - `MimeMessageBuilder` โ MIME ํ์์ ๋ฉ์์ง ์์ฑ
+ - `MAIL FROM` `RCPT TO` `DATA` โ SMTP ์๋ฒ์ ์ด๋ฉ์ผ ์ ์ก
+ - MIME ๋ฉ์์ง๋ฅผ ์์ฑ ํ, ์ฒจ๋ถ ํ์ผ์ด ์์ ๊ฒฝ์ฐ ํจ๊ป ์ ์ก
+ - `Quit`
+ - SMTP ์๋ฒ ์ฐ๊ฒฐ ์ข
๋ฃ
+ - ์์ผ, ์คํธ๋ฆผ ๋ซ์ ๋ชจ๋ ์์ ํด์
+ - `sendNoop`
+ - `NOOP`โ ์๋ฒ ์ฐ๊ฒฐ ์ ์ง. ์๋ฒ ์๋ต์ด ์ฑ๊ณต ์ฝ๋(2xx, 3xx)๋ก ์์ํ์ง ์์ผ๋ฉด ์์ธ
+ - `Response`
+ - `getSingleResponse()`: ํ ์ค์ ์๋ฒ ์๋ต์ ์ฝ๊ณ , ์ด๋ฅผ ์ถ๋ ฅ ๋ฐ ๋ฐํ
+ - `get250Response()`: `250-`์ผ๋ก ์์ํ๋ ๋ค์ค ๋ผ์ธ ์๋ต ์ฒ๋ฆฌ, ๊ฐ ์๋ต์ ๋ฐฐ์ด๋ก ๋ฐํ
+ - `checkResponse`: ์๋ต ์ฝ๋๊ฐ 2xx ๋๋ 3xx๋ก ์์ํ๋ฉด ์ฑ๊ณตํ ์๋ต์ผ๋ก ๊ฐ์ฃผ
+ - `toString`
+ - SMTP ์๋ฒ์ ๋ฉ์ผ ์ ๋ณด๋ฅผ ๋ฐํํ๋ ๋ฌธ์์ด์ ์ ๊ณต
+
+### 4. *flatlaf-3.5.2.jar*
- // ์ฒจ๋ถ ํ์ผ ์ฒ๋ฆฌ
- // FileHandler ์์ฑํด์ฃผ์ ํจ์ ์ฌ์ฉํด์ ์ฒ๋ฆฌํ๋ฉด ๋ ๋ฏํฉ๋๋ค.
-
- // ์ด๋ฉ์ผ ์ ์ก ์ข
๋ฃ
- writer.write("\r\n--boundary--\r\n.\r\n"); // ์ข
๋ฃ ํ์
- writer.flush();
- readResponse(reader);
-
- // QUIT ๋ช
๋ น์ผ๋ก ์ฐ๊ฒฐ ์ข
๋ฃ
- sendCommand(writer, "QUIT"); // ์ข
๋ฃ
- System.out.println("์ด๋ฉ์ผ์ด ์ฑ๊ณต์ ์ผ๋ก ์ ์ก๋์์ต๋๋ค.");
- return true; // ์ฑ๊ณตํ๋ฉด true ๋ฐํ
-
- } catch (IOException e) { // ์ค๋ฅ ์ฒ๋ฆฌ
- e.printStackTrace();
- System.out.println("์ด๋ฉ์ผ ์ ์ก ์คํจ.");
- return false; // ์คํจํ๋ฉด false ๋ฐํ
- }
- }
-
- // SMTP ์๋ฒ์ ๋ช
๋ น์ด ์ ์ก ๋ฉ์๋
- // writer ๋ช
์ + ๋ช
๋ น์ด(String) ํ์์ผ๋ก ์์ฑ
- private void sendCommand(BufferedWriter writer, String command) throws IOException {
- writer.write(command + "\r\n"); // ๋ช
๋ น์ด ์ ์ก
- writer.flush(); // ๋ฒํผ ๋น์
- }
-
- // SMTP ์๋ฒ์ ์๋ต์ ์ฝ๊ณ ์ถ๋ ฅ
- private String readResponse(BufferedReader reader) throws IOException {
- String response = reader.readLine(); // ์๋ต ์ฝ์
- System.out.println("Server: " + response); // ์๋ฒ ์๋ต ์ถ๋ ฅ
- return response; // ์๋ต ๋ฐํ
- }
-}
-
-```
-
-
-- `Auth.java`: ์ฌ์ฉ์ ์ธ์ฆ ๋ฐ SMTP ์๋ฒ ์ฐ๊ฒฐ ์ฒ๋ฆฌ
-- `Client.java`: ์ด๋ฉ์ผ ์ ์ก ๋ฐ ํ์ผ ์ฒจ๋ถ ๊ด๋ จ ๊ธฐ๋ฅ
+ - `FlatLaf`: GUI ํ
๋ง๋ฅผ ์ ๊ณตํ๋ ์คํ ์์ค `Look and Feel library`
+ - ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณต๋๋ `Look and Feel`์ ๋์ฒดํ์ฌ ํ๋์ ์ด๊ณ ์ธ๋ จ๋ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํ
+ - Light, Dark, IntelliJ, Darcula ์ ํ
๋ง ์ ๊ณต
+ - ๋ค์ํ ์ด์ ์ฒด์ (Windows, macOS, Linux ๋ฑ)์์ ์ผ๊ด๋ UI๋ฅผ ์ ๊ณต
+