메일 발송 서비스를 개발하기 위해서 검토를 진행하였습니다.

메일 발송과 같은 도메인(비지니스) 로직이 없고 복잡한 기술 중심의 기능이 아니면 우선순위가 낮아 일단 안전하게 실행만 된다는 생각으로 별도의 검토 없이 개발을 진행했습니다. 최근에는 마음의 여유가 생겨 우선순위가 낮은 부분에 대해서도 의미를 부여하고 부여된 의미만큼 결과에 만족하는 긍정적인 사이클이 형성되고 있는 것 같습니다.

기존에 해왔던 방식은 System.Net.Mail.SmtpClient을 사용하던 방식입니다. 사용방식이 어려운건 아니라 그냥 사용해도 무방합니다. 다른 방법이나 아이디어를 얻기 위해서 오픈 소스를 검색해보았습니다.


1번째로 살펴볼 FluentEmail의 사용하는 코드는 아래와 같습니다.

 // Using Razor templating package

Email.DefaultRenderer = new RazorRenderer();

var template = "Dear @Model.Name, You are totally @Model.Compliment.";

var email = Email
    .From("bob@hotmail.com")
    .To("somedude@gmail.com")
    .Subject("woo nuget")
    .UsingTemplate(template, new { Name = "Luke", Compliment = "Awesome" });

=> 사용이 편리해 보이지만 String.Format이나 $"{}"을 사용하면 동일하게 템플릿이 작성되는거 같아 잔기술 느낌이 납니다.

=> Fluent라는 이름이 붙으면 Method Chaining(.을 붙여서 연결하는 것)과 기존 클래스들을 랩핑하는 느낌인데 코드의 양이 엄청 줄거나 사용을 쉽게 하는 것외에 다른 핵심적인 내용이 없어 보입니다.


2번째로 살펴볼 오픈 소스는 PreMailer.Net 입니다. stylesheets에 선언된 내용이 inline style attribute로 추가해주는 라이브러리입니다. 일단 제가 원하는 것은 메일 발송이였기 때문에 거리는 있지만 이메일 양식과 관련된 내용이라 좀 더 살펴보았습니다.


[TestMethod]

public void MoveCssInline_RespectExistingStyleElement()

{

string input = "<html><head><style type=\"text/css\">.test { height: 100px; }</style></head><body><div class=\"test\" style=\"width: 100px;\">test</div></body></html>";


var premailedOutput = PreMailer.MoveCssInline(input, false);


Assert.IsTrue(premailedOutput.Html.Contains("<div class=\"test\" style=\"height: 100px;width: 100px"));

}

=> 해당 라이브러리의 기본 기능은 head 사이에 style이 div 태그 사이에 style에 적용되는 것입니다. 그 외에도 HTML태그에 대한 대문자 -> 소문자로 변경해준다던지 유효하지 않은 문법도 확인 할 수 있습니다. 그렇다면 이런 라이브러리는 왜 필요한 것일까요? 앞에 기능을 중심으로 생각해보면 외부 링크로 설정된 스타일이 포함된 경우 메일로 전송을 하게 되면 보안상(메일을 열었을 때 외부 링크에서 스타일을 받아와야 하므로) 좋지 않기 때문으로 추측됩니다.


3번째로 살펴볼 오픈 소스는 MailKit 입니다. 기존에 SmtpClient을 사용한 것이 아니라 RFC(표준)를 준수하며 크로스 플랫폼에서 사용이 가능하도록 구현한 라이브러리입니다. .NET에서 크로스 플랫폼 이야기가 나오면 .NET Core를 떠올리게 되는데 SmtpClient은 .NET Core에 포함되어 있지 않기 때문에 리눅스 환경에서는 MailKit을 사용하면 메일 발송을 할 수가 있습니다. 

MailKit에는 추가적으로 더 의미가 있는 점이 있는데 바로 성능이 우수하다는 것입니다. 성능이 우수한 이유를 PIPELINING 기술을 통해서 설명하고 있습니다.

https://tools.ietf.org/html/rfc2920


아래는 그림은 HTTP PIPELINING에 해당하는 그림으로 해당 용어에 대한 개념을 이해하기가 더 쉽습니다.


=> 왼쪽 그림은 요청에 대한 응답이 오기 전까지 다른 요청을 할 수 없는 구조이지만 오른쪽 그림은 요청과 응답에 대한 병렬처리가 가능하다는 것이 핵심입니다. HTTP PIPELINING은 HTTP 1.1부터 지원이 된다고 하며 자세한 내용은 아래 위키를 참고 하시면 됩니다.

https://en.wikipedia.org/wiki/HTTP_pipelining


결론적으로 크로스플랫폼 지원과 성능이 우수한 MailKit 을 사용하려고 하였는데 StackExchange.Exceptional에 예외 로그를 저장하면서 메일을 전송해주는 부분이 함께 있어 해당 부분을 사용하기로 결정하였습니다. 해당 부분은 예외 로그에 대한 메일 전송이고 메일 발송 서비스만을 위해서는 MailKit과 PreMailer.NET까지 고려해서 차후에 개발해볼 예정입니다.

P.S : 7월22일에 처음 썼던 글인데 게으름이 생겨 이제야 마무리를 했네요 ^^;


Posted by resisa