source

Java 주석을 사용하여 Spring과 함께 전자 메일 보내기

manysource 2023. 6. 24. 09:20

Java 주석을 사용하여 Spring과 함께 전자 메일 보내기

Java 구성 규칙에 따라 순수 주석 기반 접근 방식을 사용하여 Spring 4(및 Spring Boot)로 이메일을 보낼 수 있는 방법은 무엇입니까?

전자 메일 서비스를 구성하기 위한 간단한 솔루션(인증 없이 SMTP 서버를 사용할 경우)은 다음과 같습니다.

@Configuration 
public class MailConfig {

    @Value("${email.host}")
    private String host;

    @Value("${email.port}")
    private Integer port;

    @Bean
    public JavaMailSender javaMailService() {
        JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();

        javaMailSender.setHost(host);
        javaMailSender.setPort(port);

        javaMailSender.setJavaMailProperties(getMailProperties());

        return javaMailSender;
    }

    private Properties getMailProperties() {
        Properties properties = new Properties();
        properties.setProperty("mail.transport.protocol", "smtp");
        properties.setProperty("mail.smtp.auth", "false");
        properties.setProperty("mail.smtp.starttls.enable", "false");
        properties.setProperty("mail.debug", "false");
        return properties;
    }
}

스프링이 특성을 해결할 수 있어야 합니다.email.host그리고.email.port일반적인 방법으로 (Spring Boot의 경우 가장 간단한 방법은 application.properties에 넣는 것입니다.)

JavaMailSender의 서비스가 필요한 모든 클래스에서 일반적인 방법 중 하나(예:@Autowired private JavaMailSender javaMailSender)


갱신하다

버전 1.2.0부터입니다.RC1 Spring Boot 자동 구성 가능JavaMailSender널 위해서.설명서의 이 부분을 확인하십시오.설명서에서 알 수 있듯이, 설치 및 실행에 구성이 거의 필요하지 않습니다!

pom.xml:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>

application.properties:

spring.mail.host=...
spring.mail.port=...

Foo.java:

@Component
public class Foo {

    @Autowired
    private JavaMailSender mailSender;

    public void send() {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom("foo@example.com");
        message.setTo("bar@example.com");
        message.setSubject("hello");
        mailSender.send(message);
    }
}

개인적으로 로컬 호스트 MTA를 실행하여 실제 MTA(예: Gmail 또는 SES 또는 자신의 MTA)로 릴레이하는 데 사용할 것을 권장합니다.그러면 "사용 가능한" 비동기 대기열이 제공되고 구성이 중앙 집중화됩니다.저는 OpenSMTP를 좋아합니다.

Spring-Boot를 사용하면 smtp.office365.com 메일 서버에 한 가지 조정이 필요할 정도로 사소한 것에 가까웠습니다. 이는 이 회사가 사용하는 것입니다.

이렇게 조정하기 전에 Office365 SMTP 서버에 대한 인증이 계속 실패하여 다음과 같은 오류가 발생했습니다.

org.springframework.mail.MailSendException: Failed messages: com.sun.mail.smtp.SMTPSendFailedException: 530 5.7.57 SMTP; Client was not authenticated to send anonymous mail during MAIL FROM
    at org.springframework.mail.javamail.JavaMailSenderImpl.doSend(JavaMailSenderImpl.java:474)
    at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:307)
    at org.springframework.mail.javamail.JavaMailSenderImpl.send(JavaMailSenderImpl.java:296)

이는 Spring의 MailProperties 클래스에서 올바르게 선택되는 사용자 이름과 암호를 설정하는 경우에도 마찬가지입니다.

Office365는 TLS 인증을 활성화해야 하며 Spring의 현재 JavaMail 구현에서는 속성으로 이를 수행할 수 있는 간단한 방법이 없습니다.해결책은 우리만의 javax.mail을 만드는 것입니다.세션 인스턴스를 Spring에 등록합니다.

전체 그림은 다음과 같습니다.

pom.xml 파일에서 다음을 추가합니다.

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-mail</artifactId>
        <version>${spring-boot.version}</version>
    </dependency>

스프링 부츠를 신는 곳.버전은 다른 곳에서 정의되며(이 경우 부모 폼에서) 이 경우 1.3.1의 값을 갖습니다. RELEASE

기본 응용 프로그램에서 항목화하는 경우 패키지 및/또는 자동 구성 클래스를 포함해야 합니다. 기본 @SpringBootApplication을 사용하는 경우에는 이 클래스가 필요하지 않지만, 제 경우에는 MailSenderAutoConfiguration.class를 @Import 주석의 클래스 목록에 추가했습니다.

간단한 EmailSender 클래스를 만들었습니다.

@SuppressWarnings("SpringJavaAutowiringInspection")
@Slf4j
@Service
@ConditionalOnClass(JavaMailSender.class)
public class EmailSender {

    @Autowired
    private EventBus mmEventBus;

    @Autowired
    private JavaMailSender mailSender;

    @Autowired
    private MessageConfig messageConfig;

    @Subscribe
    public void sendEmail(EmailMessageEvent eme) {
        log.info("{}", eme);

        SimpleMailMessage msg = new SimpleMailMessage(messageConfig.getMessageTemplate());
        msg.setSubject(eme.getSubject());
        msg.setText(eme.getMessage());

        try {
            mailSender.send(msg);
        } catch (MailException ex) {
            log.error("Error sending mail message: " + eme.toString(), ex);
        }
    }

    @PostConstruct
    public void start() throws MessagingException {
        mmEventBus.register(this);
    }

}

여기서 @Slf4j는 롬복 주석이고, @Subscribe는 Guava의 EventBus를 위한 것이며, 이것은 이 앱이 EmailSender가 보낼 메시지가 있음을 알리는 방법입니다.저는 제목과 메시지 텍스트가 있는 사소한 EmailMessageEvent POJO를 사용합니다. 이 앱의 목적에 충분히 적합합니다.

MessageConfig 클래스를 사용하면 응용 프로그램의 나머지 구성과 함께 메시지 기본값을 쉽게 설정할 수 있으며 Office365 SMTP 서버에서 사용자 지정 javax.mail을 사용하는 데 필요한 특수 소스가 하나 있습니다.Spring Bean으로 등록된 세션 인스턴스:

@Data
@Component
@ConfigurationProperties(prefix = "spring.message", ignoreUnknownFields = false)
@Slf4j
public class MessageConfig {

    @SuppressWarnings("SpringJavaAutowiringInspection")
    @Autowired
    private MailProperties mailProperties;

    private String from;
    private String subject;
    private String[] recipients;

    private SimpleMailMessage messageTemplate;

    public void setRecipients(String... r) {
        this.recipients = r;
    }

    @PostConstruct
    public void createTemplate() {
        messageTemplate = new SimpleMailMessage();
        messageTemplate.setFrom(from);
        messageTemplate.setSubject(subject);
        messageTemplate.setTo(recipients);

        log.debug("Email Message Template defaults: {}", messageTemplate);
    }

    @Bean
    public SimpleMailMessage getMessageTemplate() {
        return messageTemplate;
    }

    @Bean
    public Session getSession() {
        log.debug("Creating javax.mail.Session with TLS enabled.");
        // We could be more flexible and have auth based on whether there's a username and starttls based on a property.
        Properties p = new Properties();
        p.setProperty("mail.smtp.auth", "true");
        p.setProperty("mail.smtp.starttls.enable", "true");
        p.setProperty("mail.smtp.host", mailProperties.getHost());
        p.setProperty("mail.smtp.port", mailProperties.getPort().toString());
        return Session.getDefaultInstance(p, new Authenticator() {
            @Override
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(mailProperties.getUsername(), mailProperties.getPassword());
            }
        });
    }

}

@Data는 다시 롬복 주석입니다. String(), equals() 및 hashCode() 등에 돌연변이 및 접근자 메서드를 자동으로 추가합니다.

Spring의 JavaMailSender(JavaMailSenderImppl)의 한계는 세션을 직접 구성할 수 없으며, 특히 속성을 통한 TLS 인증을 사용할 수 없다는 것입니다.하지만 javax.mail이 있다면,MailSenderAutoConfiguration에 주입(조건부 자동 배선)된 다음 JavaMailSenderImpl 인스턴스를 구성하는 데 사용되는 컨텍스트에 등록된 세션 빈입니다.

따라서 getSession() 메서드를 통해 이러한 Bean만 등록합니다.좋은 측정을 위해 여기서 구성하는 세션을 JVM의 기본 세션으로 만듭니다. 이러한 동작을 원하지 않는 경우 getInstance()라고 부르도록 변경합니다.

이 세션 @Bean을 추가한 후 모든 것이 작동했습니다.

Spring Boot 1.2 이상을 사용하면 JavaMailSender를 자동으로 구성할 수 있습니다.Spring Boot 1.2 이후 버전을 사용하여 메일을 보내는 정확한 방법을 설명하는 이 비디오를 받았습니다.스프링 레몬의 소스 코드는 정확한 세부 정보를 참조할 수 있습니다.

Geoand의 답변 외에도, 메일 속성을 하드 코딩하거나 XML을 작성하지 않으려면 리소스의 파일(예: mail.properties)에 속성을 추가하고 MailConfig 클래스에 다음과 같은 코드를 추가할 수 있습니다.

@Resource(name = "mailProperties")
private Properties mailProperties;

@Bean(name = "mailProperties")
public PropertiesFactoryBean mapper() {
    PropertiesFactoryBean bean = new PropertiesFactoryBean();
    bean.setLocation(new ClassPathResource("mail.properties"));
    return bean;
}

사용할 수 있는 속성의 범위는 모두 이 페이지에서 정의됩니다.

https://javamail.java.net/nonav/docs/api/

https://javamail.java.net/nonav/docs/api/com/sun/mail/smtp/package-summary.html

그러나 JavaMailSenderImppl의 메서드에서 Host, Port, Username 및 Password를 설정해야 합니다. 이 메서드는 속성에 설정된 메서드를 직접 사용하지 않기 때문입니다.

언급URL : https://stackoverflow.com/questions/22483407/send-emails-with-spring-by-using-java-annotations