아래와 같은 환경에서 기본적으로 메일 전송 기능 구현을 진행.

 

 

- Apache Maven 4.0.0

- JDK 1.8

- Spring 4.3.9.RELEASE

 

 

 


 

 

 

1. pom.xml

 다음과 같이 메일에 관련된 dependency를 pom.xml 에 추가한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>javax.mail-api</artifactId>
            <version>1.5.5</version>
        </dependency>
 
        <dependency>
            <groupId>javax.mail</groupId>
            <artifactId>mail</artifactId>
            <version>1.4.7</version>
        </dependency>
 
cs

 

 

 

 

2. Mail Service

 MailService 인터페이스를 생성한다.

 

1
2
3
4
5
public interface MailService {
 
    public void sendEmail(String content);
}
 
cs

 

 

 

 

3. Mail Service 구현

MailService interface 를 상속받아 구현한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import javax.mail.internet.MimeMessage;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.stereotype.Service;
 
import com. ... .Mail;
 
@Service("mailService")
public class MailServiceImpl implements MailService {
 
    @Autowired
    JavaMailSender mailSender;
 
    @Override
    public void sendEmail(Mail mail) {
 
        final MimeMessagePreparator preparator = new MimeMessagePreparator() {
            @Override
            public void prepare(MimeMessage mimeMessage) throws Exception {
                final MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true"UTF-8");
                
                helper.setFrom(mail.getMailFrom()); // recipient
                helper.setTo(mail.getMailTo()); //sender
                helper.setSubject(mail.getMailSubject()); // mail title
                helper.setText(mail.getMailContent(), true); // mail content
            }
        };
 
        mailSender.send(preparator);
    }
}
 
cs

 

 

 

 

4. Mail Configuration

host, port 번호, 사용자 계정과 같은 Gmail SMTP 설정 값을 정의하고 mail 속성 값 또한 정의한다.

※ @Configuration @Bean 에 대한 설명은 아래 글 참고

    [클릭]▶▶ 2019/08/02 - [ └ JAVA] - [Spring] 자주 쓰는 스프링(Spring framework) 어노테이션(Annotation) 정리

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import java.util.Properties;
 
import org.apache.velocity.app.VelocityEngine;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
 
@Configuration
public class MailConfig {
    
    @Bean
    public JavaMailSender getMailSender() {
        
        JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
        
        mailSender.setHost("smtp.gmail.com");
        mailSender.setPort(587);
        mailSender.setUsername("your-email");
        mailSender.setPassword("your-password");
        
        Properties javaMailProperties = new Properties();
        
        javaMailProperties.put("mail.smtp.starttls.enable""true");
        javaMailProperties.put("mail.smtp.auth""true");
        javaMailProperties.put("mail.transport.protocol""smtp");
        javaMailProperties.put("mail.debug""true");
 
        mailSender.setJavaMailProperties(javaMailProperties);
        
        return mailSender;
    }
}
cs

 

 

 

 

 

5. Mail Pojo

메일의 상세 값을 담고 있을 pojo 클래스를 생성한다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
import java.util.Date;
 
public class Mail {
 
    private String mailFrom;
 
    private String mailTo;
 
    private String mailCc;
 
    private String mailBcc;
 
    private String mailSubject;
 
    private String mailContent;
 
    private String contentType;
 
    public Mail() {
        contentType = "text/plain";
    }
 
    public String getContentType() {
        return contentType;
    }
 
    public void setContentType(String contentType) {
        this.contentType = contentType;
    }
 
    public String getMailBcc() {
        return mailBcc;
    }
 
    public void setMailBcc(String mailBcc) {
        this.mailBcc = mailBcc;
    }
 
    public String getMailCc() {
        return mailCc;
    }
 
    public void setMailCc(String mailCc) {
        this.mailCc = mailCc;
    }
 
    public String getMailFrom() {
        return mailFrom;
    }
 
    public void setMailFrom(String mailFrom) {
        this.mailFrom = mailFrom;
    }
 
    public String getMailSubject() {
        return mailSubject;
    }
 
    public void setMailSubject(String mailSubject) {
        this.mailSubject = mailSubject;
    }
 
    public String getMailTo() {
        return mailTo;
    }
 
    public void setMailTo(String mailTo) {
        this.mailTo = mailTo;
    }
 
    public Date getMailSendDate() {
        return new Date();
    }
 
    public String getMailContent() {
        return mailContent;
    }
 
    public void setMailContent(String mailContent) {
        this.mailContent = mailContent;
    }
 
}
cs

 

 

 

 

6. App.java

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
 
import com. ... .Mail;
import com. ... .MailConfig;
import com. ... .MailService;
 
public class App {
 
    public static void main(String args[]) {
 
        Mail mail = new Mail();
        mail.setMailFrom("from@gmail.com");
        mail.setMailTo("to@gmail.com");
        mail.setMailSubject("This is Email test.");
        mail.setMailContent("Learn how to send email using Spring.");
 
        AbstractApplicationContext context = new AnnotationConfigApplicationContext(MailConfig.class);
        MailService mailService = (MailService) context.getBean("mailService");
        mailService.sendEmail(mail);
        context.close();
    }
 
}
cs

 

 

 

 

7. 메일 전송 테스트

서버를 켜고 실제 메일 테스트를 하면 아래와 같은 로그를 확인할 수 있다면 메일 전송 성공!

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
DEBUG: JavaMail version 1.5.5
DEBUG: successfully loaded resource: /META-INF/javamail.default.providers
DEBUG: Tables of loaded providers
DEBUG: Providers Listed By Class Name: {com.sun.mail.smtp.SMTPSSLTransport=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], 
com.sun.mail.smtp.SMTPTransport=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle], 
com.sun.mail.imap.IMAPSSLStore=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], 
com.sun.mail.pop3.POP3SSLStore=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], 
com.sun.mail.imap.IMAPStore=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], 
com.sun.mail.pop3.POP3Store=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle]}
DEBUG: Providers Listed By Protocol: {imaps=javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle], 
imap=javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle], smtps=javax.mail.Provider[TRANSPORT,smtps,com.sun.mail.smtp.SMTPSSLTransport,Oracle], 
pop3=javax.mail.Provider[STORE,pop3,com.sun.mail.pop3.POP3Store,Oracle], pop3s=javax.mail.Provider[STORE,pop3s,com.sun.mail.pop3.POP3SSLStore,Oracle], 
smtp=javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]}
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "smtp.gmail.com", port 587, isSSL false
220 smtp.gmail.com ESMTP r1sm4343180pgv.70 - gsmtp
DEBUG SMTP: connected to host "smtp.gmail.com", port: 587
 
EHLO DESKTOP-PI4HNSK
250-smtp.gmail.com at your service, [220.86.211.178]
250-SIZE 35882577
250-8BITMIME
250-STARTTLS
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-CHUNKING
250 SMTPUTF8
DEBUG SMTP: Found extension "SIZE", arg "35882577"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "STARTTLS", arg ""
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
DEBUG SMTP: Found extension "SMTPUTF8", arg ""
STARTTLS
220 2.0.0 Ready to start TLS
EHLO DESKTOP-PI4HNSK
250-smtp.gmail.com at your service, [220.86.211.178]
250-SIZE 35882577
250-8BITMIME
250-AUTH LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH
250-ENHANCEDSTATUSCODES
250-PIPELINING
250-CHUNKING
250 SMTPUTF8
DEBUG SMTP: Found extension "SIZE", arg "35882577"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "AUTH", arg "LOGIN PLAIN XOAUTH2 PLAIN-CLIENTTOKEN OAUTHBEARER XOAUTH"
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
DEBUG SMTP: Found extension "SMTPUTF8", arg ""
DEBUG SMTP: Attempt to authenticate using mechanisms: LOGIN PLAIN DIGEST-MD5 NTLM 
DEBUG SMTP: AUTH LOGIN command trace suppressed
DEBUG SMTP: AUTH LOGIN succeeded
DEBUG SMTP: use8bit false
MAIL FROM:<"보내는 메일 주소">
250 2.1.0 OK r1sm4343180pgv.70 - gsmtp
RCPT TO:<"받는 메일 주소">
250 2.1.5 OK r1sm4343180pgv.70 - gsmtp
DEBUG SMTP: Verified Addresses
DEBUG SMTP:   "받는 메일 주소"
DATA
354  Go ahead r1sm4343180pgv.70 - gsmtp
Date: Fri, 16 Aug 2019 18:30:53 +0900 (KST)
From: dug20.notifier@gmail.com
To: hyewon.lee@doubleugames.com
Message-ID: <167656150.2.1565947853279@DESKTOP-PI4HNSK>
Subject: "메일 제목"
 
"▼그 밖에 메일 상세 내용들 ..."
....
....
....
....
MIME-Version: 1.0
cs

 

 

 

 

 

 

 

 

 

 

[참고] 
https://www.technicalkeeda.com/spring-tutorials/how-to-send-email-using-spring-4

 

간단하지만 할 때마다 검색하게 되는 것.. 기록하기.

 

 

JAVA 현재 시간과 날짜 구하기.

1
2
3
4
5
6
7
8
9
10
11
// 현재 시스템 시간 구하기
long systemTime = System.currentTimeMillis();
 
// 출력 형태를 위한 formmater 
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.KOREA);
 
// format에 맞게 출력하기 위한 문자열 변환
String dTime = formatter.format(systemTime);
 
System.out.println("Today is " + dTime); // 'Today is 2019-08-16 12:44:42' 출력
 
cs

 

 

 

 

 

@Autowired

 의존 관계를 자동 설정 할 때 사용하며 타입을 이용하며 의존하는 객체를 주입한다. @Autowired 를 사용하면 new 연산자를 통해 객체를 생성하지 않아도 접근이 가능하다. 따라서 해당 타입의 bean 객체가 존재하지 않거나 두개 이상이면 에러를 발생시킨다. 
 - @Autowired(required=false) 라고 사용하면 해당 타입의 객체가 존재하지 않아도 에러가 발생하지 않는다.
 - 같은 타입의 bean 객체가 두 개 이상 존재 할 때 @Qualifier('Bean 이름') 처럼 bean 이름을 지정해 주면 에러가 발생하지 않는다.

 

@Component

  Autowired 할 클래스 위에 명시한다.

 

@Bean

 리턴값이 컴포넌트가 되도록 한다. 
@Configuration 안에 있어야 bean이 생성된다.

1
2
3
4
5
6
7
8
9
10
@Configuration
public interface BeanInterface {
 
    @Bean
    default SomeBean someBean() {
 
        return new SomeBean();
  }
}
 
cs

 

@Service

 Service 클래스에 쓰인다. 비지니스 로직을 수행하는 클래스라는 의미를 타나낸다.

 

@Controller

 Controller 클래스에 쓰인다.

 

@Resource

 @Autowired 와 쓰임이 비슷하지만 타입이 아닌 이름으로 연결된다는 차이점이 있다.
Ex) @Resource(name="bean 이름")

 

@Value

 프로퍼티에서 값을 가져와 주입한다.

1
2
3
@Value("${system.mail.from}")
private String mailFrom;
 
cs

 

@RestController

 @Controller@ResponseBody 를 합쳐놓은 의미로서 리턴되는 값이 View 로 응답하는 것이 아닌 HttpResponse 로 바로 응답한다.

 

@RequestMapping

 요청받은 URL 을 어떤 메소드가 처리할 지 매핑해주는 역할을 한다.

1
2
3
4
5
6
7
8
9
10
11
12
/**
 * 요청 URL 예시 : https://localhost:8443/admin-web/api/projects
 *
 **/
@RestController
@RequestMapping(value = "/api/projects")
public class ProjectController {
 
    // ... logic area
 
}
 
cs

 

 

@PathVariable

 요청 URL 중 변수값을 파싱한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
 * 요청 URL 예시 : [GET] https://localhost:8443/admin-web/api/projects/1
 *
 **/
@RestController
@RequestMapping(value = "/api/projects")
public class ProjectController {
 
 
    @GetMapping("/{id}")
    public ResponseEntity find(@PathVariable(value = "id") Long id) {
        
        // ... logic here
 
    }
 
}
 
cs

 

@RequestBody

 POST, PUT 등으로 요청 받았을 때, 요청 값으로 넘어오는 body 값 들을 자바 타입으로 파싱한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
 * 요청 URL 예시 : [POST] https://localhost:8443/admin-web/api/projects/1
 *
 **/
@RestController
@RequestMapping(value = "/api/projects")
public class ProjectController {
 
 
    @GetMapping("/{id}")
    public ResponseEntity find(@PathVariable(value = "id") Long id) {
        
        // ... logic here
 
    }
 
    @PostMapping("/{id}")
    public ResponseEntity find(@PathVariable(value = "id") Long id, @RequestBody Module paramModule) {
        
        // ... logic here
    }
 
}
 
cs

 

@RequestParam

 '?paramName=paramValue' 와 같은 쿼리 파라미터를 파싱한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
 * 요청 URL 예시 : [GET] https://localhost:8443/admin-web/api/projects/1?paramNm=test
 *
 **/
@RestController
@RequestMapping(value = "/api/projects")
public class ProjectController {
 
 
    @GetMapping("/{id}")
    public ResponseEntity find(@PathVariable(value = "id") Long id, @RequestParam String paramNm) {
        
        // ... logic here
 
    }
 
}
 
cs

 

 

 


 

계속 추가될 예정 ...

2019/08/01  최초 작성

 

 

[참고] 
https://medium.com/@aaaalpooo/%EB%A7%8E%EC%9D%B4-%EC%93%B0%EB%8A%94-spring-framework-annotation-%EC%A0%95%EB%A6%AC-summary-of-annotations-frequently-used-in-spring-framework-935e1c1a4877

https://backback.tistory.com/115

 

 

 

 

+ Recent posts