콘텐츠로 이동

2021 12 21

2021-12-21

DKIM 적용하기

  • OpenDKIM 설치 - $ sudo apt-get install opendkim opendkim-tools
  • DKIM 이론 - 발신자가 발신 메시지에 암호로 서명하고, 다른 확인 메타데이터와 함께 DKIM-Signature에 포함시켜 전송 - 발신자는 DNS에 공개키를 게시 - DKIM을 구현하기 위해 전송조직은 하나의 공개키쌍을 생성하고, DNS에 공개키를 TXT레코드로 게시 - 각 키쌍은 "selector"에서 참조 - 다음과 같이 서명 - a: 서명에 사용될 알고리즘 - c: 정규화 체계 지정 - s: 선택키 또는 키 참조 - d: 서명 도메인 - h: 서명된 헤더를 나열 - i: 서명 사용자 id
    DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=info.verbling.com;
    h=content-type:from:mime-version:subject:reply-to:x-feedback-id:to;
    s=s1; bh=yurMcrg5W97a0bnM840AyZYyEnx4j8QZcGCRwB4r6eM=;
    b=qEiTpG63wwKCYlEPQ05DfLtq5OzIgvT5qgKwhqn0h6IN/3khkA7pfD5C33a9phS+MBTH
    cGIUgYoeUBeFHB1xluq/zxi9D/qyxfznfl++2GsJY5FK6emKhrCPpuMBCrjFyspyuMfClZ
    EFqT33dTpty4jKzhbe2YMJUfFKfP1AZ8ENQN/+GvjDufjguwBUJ0PhEZrH8NCnsheszPw9
    gu9Sb5abx5WsCbvoUBJtDaXgwyLDpAwwgK6H6NgPw1Zt96a531KjM7053omFk2zu872lnG
    uk74LtvEc5MUglVqbvHevFk74CUsxHUCaoTlKNq14UQCtVdZ3jT/R2NQwbQ3nZeg==
    

    - DKIM 서명 메시지를 수신하면 다음 DNS 쿼리를 구성해 공개키 조회 - selector._domainkey.cstoday.me - 버블링 예시: s1._domainkey.info.verbling.com -

  • 드디어 성공한 DKIM - 자바에서는 pem 말고 der 양식의 인증서만 읽을 수 있음 - 따라서 파일로써 읽은 다음에 인증에 사용하도록 코드를 구현 - 요런 갬성
    @Service
    public class MailSenderService {
    
        private static final String WELCOME_MAIL_SUBJECT = "오늘의 CS를 구독해주셔서 감사합니다 🎁";
        private static final String NEWSLETTER_SUBJECT = "오늘의 CS 뉴스레터입니다 🎁";
        private static final String SERVER_MAIL_NAME = "오늘의 CS";
        private static final String SERVER_MAIL_ADDRESS = "cstoday@cstoday.me";
    
        private Mailer mailer;
        private File dkimFile;
    
        @Value("${setting.dkim}")
        private String dkimFilePath;
    
        @Value("${spring.mail.host}")
        private String mailHost;
    
        @Value("${spring.mail.port}")
        private Integer mailPort;
    
        @Value("${spring.mail.username}")
        private String mailUsername;
    
        @Value("${spring.mail.password}")
        private String mailPassword;
    
        @PostConstruct
        public void init() {
             mailer = MailerBuilder
                    .withSMTPServer(mailHost, mailPort, mailUsername, mailPassword)
                    .withTransportStrategy(TransportStrategy.SMTP_TLS)
                    .withProperty("mail.smtp.auth", true)
                    .withProperty("mail.smtp.timeout", 5000)
                    .withProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory")
                    .withProperty("mail.smtp.starttls.enable", true)
                    .buildMailer();
    
             dkimFile = new File(dkimFilePath);
        }
    
        public void sendWelcomeMail(String destination) {
            final Email email = generateEmail(destination, WELCOME_MAIL_SUBJECT, WelcomeMail.welcomeMailContent);
            mailer.sendMail(email);
        }
    
        public void sendNewsLetter(String destination, String content) {
            final Email email = generateEmail(destination, NEWSLETTER_SUBJECT, content);
            mailer.sendMail(email);
        }
    
        private Email generateEmail(String destination, String subject, String content) {
            return EmailBuilder.startingBlank()
                    .to(destination)
                    .from(SERVER_MAIL_NAME, SERVER_MAIL_ADDRESS)
                    .withSubject(subject)
                    .withHTMLText(content)
                    .signWithDomainKey(dkimFile, "cstoday.me", "mail")
                    .buildEmail();
        }
    }