태그 보관물: C#

C# POP3, IMAP 메일 읽어오기

개요

여러가지 이유로 특정 계정의 메일을 읽어와야 할 경우가 있습니다. 필자의 경우 특정한 형식의 메일로 자료를 받아오는 처리를 하게되었습니다. 메일서버와 통신하는 프로토콜은 POP3, IMAP 이 있는데 모두 알아보도록 하겠습니다.

POP3

프로토콜 자체에 대한 설명은 자료를 찾아보면 많이 있습니다. 이번 포스트에서는 서버에 접속해서 목록과 내용을 가져오는 부분을 중점적으로 살펴 보겠습니다. 메일을 읽어오는 방식이 여러가지 방법이 있지만 잘 만들어진 라이브러리를 이용하는 것이 효율적입니다. 여러가지 라이브러리가 있는데 OpenPop.NET 를 사용하겠습니다.

OpenPop.NET은 오픈소스 POP3 client 라이브러리 입니다. 설치는 패키지 관리자 콘솔에서 다음과 같이 입력하면 됩니다.

Install-Package OpenPop.NET

메일 목록을 가져오는 코드를 보겠습니다.

using (Pop3Client client = new Pop3Client())
{
	client.Connect("yourserver", 110, false); //서버접속

	client.Authenticate("youraccount", "yourpassword", AuthenticationMethod.UsernameAndPassword); //서버인증

	var messageCount = client.GetMessageCount(); //받은메일의 메시지 개수

	List<Message> allMessages = new List<Message>(messageCount);

	for (var i = 1; i messageCount; i++)
	{
		var message = client.GetMessage(i);
		var fromAddress = message.Headers.From.Address;
		var subject = message.Headers.Subject;
		var messageBody = String.Empty;

		var plainText = message.FindFirstPlainTextVersion();

		if (plainText == null)
		{
			var html = message.FindFirstHtmlVersion();
			messageBody = html.GetBodyAsText();
		}
		else
		{
			messageBody = plainText.GetBodyAsText();
		}

		var attachFile = message.FindAllAttachments();

		Response.Write("fromAddress : " + fromAddress + "<br />");
		Response.Write("subject : " + subject + "<br />");
		Response.Write("messageBody : " + messageBody + "<br />");
		Response.Write("attachFileCount : " + attachFile.Count + "<br />");
		Response.Write("MessageId : " + message.Headers.MessageId + "<br />");

		foreach (var currentAttachFile in attachFile)
		{
			Response.Write("currentAttachFile : " + currentAttachFile.FileName + "<br />");
			var attachFileInfo = new FileInfo(@"c:\yourpath\" + currentAttachFile.FileName);
			currentAttachFile.Save(attachFileInfo);
		}

		Response.Write("<br /><br /><br />");
	}

	Response.Write("messageCount : " + messageCount);
} 

11행과 같이 시작 인덱스가 1부터 시작한다는 것을 기억해야 합니다.

메일의 내용을 가져올 때 내용이 단순 텍스트인지 html 형태로 되어 있는지에 따로 조금 다릅니다. 일단 18행과 같이 단순 텍스트를 가져 옵니다. 텍스트의 정보가 null 이면 html 형식의 내용으로 간주해서 내용을 가져옵니다. 단순 텍스트 정보이면 그대로 내용을 가져오면 됩니다.

38행~43행은 첨부된 파일의 개수만큼 반복하면서 파일을 저장하는 부분입니다. 필요에 따라 응용하시면 됩니다.

IMAP

모든 서버가 IMAP 프로토콜을 지원하지는 않습니다. 구글메일이 IMAP 프로토콜을 지원하므로 메일을 가져오는 부분을 살펴보겠습니다. 여기에서도 ImapX 라이브러리를 사용하도록 하겠습니다. .NET 용 IMAP 라이브러리 입니다. 패키지 관리자 콘솔에서 다음과 같이 입력하면 설치됩니다.

PM> Install-Package ImapX

메일 제목을 출력하는 코드를 보겠습니다.

Imap4Client imap = new Imap4Client();

var mailServer = "yourmailserver";
var mailAddress = "yourmailaddress";
var mailPassword = "yourpassword";

try
{
	imap.ConnectSsl(mailServer);

	imap.Login(mailAddress, mailPassword);

	Mailbox inbox = imap.SelectMailbox("inbox");

	MessageCollection messages = inbox.SearchParse("OLD UNSEEN");

	if (messages.Count > 0)
	{
		for (int n = 0; n < messages.Count; n++)
		{
			Response.Write(messages[n].Subject + "");
		}
	}
}
catch (Imap4Exception iex)
{
	Response.Write("Imap4 Error: " + iex.Message + "<br />");
}
catch (Exception ex)
{
	Response.Write("Exception: " + ex.Message + "<br />");
}
finally
{
	if (imap.IsConnected)
	{
		imap.Disconnect();
	}
}

15행에 보면 문자로 된 OLD UNSEEN 부분이 있습니다. 검색 명령어인데 전체 명령어는 다음의 주소에서 확인하실 수 있습니다. 6.4.4. SEARCH Command 부분을 보시면 됩니다.

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

여러가지 조합이 가능한데 메일을 가져오는 목적에 따라 변경하시면 됩니다.

메시지를 가져온 후 속성을 살펴보면 많은 항목이 있음을 알 수 있습니다. 개발 목적에 따라 적절하게 사용하시면 됩니다.

이상 C# 과 라이브러리를 이용한 POP3, IMAP 메일 읽어오는 방법을 살펴봤습니다.

C# NLog 이용하여 WebForm, WinForm 로그 만들기

로그의 필요성

개발을 진행하면서 개발 도구를 가지고 디버깅을 하게 됩니다. WebFrom의 Javascript 부분은 console.log 로 값을 확인하거나 화면에 직접 출력해서 변수의 값을 확인합니다. 하지만 실제로 운영이 되고 있는 시스템에서 문제가 발생하면 그 상황에 대한 정보가 있어야 해결이 가능합니다. 이런 이유 때문에 로그가 필요합니다. 기본적으로는 최소화하는 것이 좋습니다. 하지만 운영 초기에는 가능한 한 로그 자료를 많이 생성합니다. 문제가 발생했을 때 해결시간을 최소화하는데 중점을 둡니다.

대부분 메소드 호출 부분에 전달된 변수의 값이나 예외의 내용을 기록합니다. 예외의 내용을 사용자에게 직접적으로 노출하지 않고 개발자가 확인할 수 있는 방법입니다.

이전에는 간단하게 텍스트 파일을 만들어 로깅을 진행했습니다. 물론 지금도 그렇게 사용해도 되지만 잘 만들어진 로그 라이브러리를 사용하는 것이 더 나은 선택입니다. 대표적인 것이 NLog, log4net 입니다. 설정이 상대적으로 쉬운 NLog 를 이용한 로깅에 대해 살펴보겠습니다.

NLog

NLog 는 무료로 사용할 수 있는 .NET용 로깅 플랫폼 입니다. 설정이 쉬운 것이 장점입니다. log4net을 사용해 본적이 있었습니다. 설정이 생각보다 쉽지는 않았던 기억이  납니다.

로그의 내용을 파일, 이벤트로그, 데이터 베이스 등에도 기록할 수 있습니다. 개발 환경에 맞게 선택해서 기록하면 됩니다. 필자는 일자별로 텍스트 파일로 기록합니다.

설치는 패키지 관리자 콘솔에서 다음 명령어를 입력하면 됩니다.

PM> Install-Package NLog.Config

WebForm(ASP.NET)

ASP.NET 프로젝트일 때 설정하는 방법을 알아보겠습니다.

설정은 파일이나 소스에 직접할 수 있습니다. 이 글에서는 파일에 설정하는 방법을 살펴보겠습니다.

NLog.config 의 내용을 수정해서 설정하면 됩니다.

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <variable name="LogDay" value="${date:format=yyyyMMdd}"/>;
    <targets>
        <target name="logfile" xsi:type="File" fileName="D:\yourserver\yourproject\log\${LogDay}.log" />
    </targets>
    <rules>
        <logger name="*" minlevel="Info" writeTo="logfile" />
    </rules>
</nlog>

3행은 일자의 형식을 지정하는 설정입니다. 20180127.log 이런식으로 파일이 생성됩니다.

5행은 실제 로그 파일이 저장될 위치입니다.

추가적인 설정은 NLog 사이트를 참고하여 필요하신 사항을 추가하시면 됩니다. 필자는 위의 설정만으로도 충분했습니다. NLog.config 파일은 web root 경로에 두시면 됩니다.

소스에서는 다음과 같이 코드를 추가해서 사용하면 됩니다.

public partial class nlog_test : System.Web.UI.Page
{
	private static Logger logger = LogManager.GetCurrentClassLogger();

	protected void Page_Load(object sender, EventArgs e)
	{
		try
		{
			logger.Info("your log text");
		}
		catch (Exception ex)
		{
			logger.Fatal("Exception occurred in Page_Load. : " + ex.Message + ";" + ex.Source);
		}
	}
}

로그 파일에는 다음과 같이 기록됩니다.

2017-12-26 00:03:46.3420|INFO||your log text
2017-12-26 00:12:27.9778|FATAL||Exception occurred in Page_Load : your error message ;mscorlib

로그 파일이 저장되는 경로가 쓰기 권한이 없으면 기록이 되지 않는 경우가 있습니다. 경로가 정확한데 로그파일이 생성되지 않는다면 인터넷 사용자(IUSR)의 쓰기 권한을 부여하시면 됩니다.

WinForm

WinForm의 경우도 설정은 같습니다. 특정한 폴더에 로그가 기록되도록 하고 싶으면 위와 같이 설정하시면 됩니다. 프로그램이 실행된 폴더의 하위에 생성되도록 하고 싶다면 다음과 같이 설정합니다.

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <variable name="LogDay" value="${date:format=yyyyMMdd}"/>
    <targets>
        <target name="logfile" xsi:type="File" fileName="log\${LogDay}.log" />
    </targets>
    <rules>
        <logger name="*" minlevel="Info" writeTo="logfile" />
    </rules>
</nlog>

이렇게 하면 프로그램이 실행된 폴더의 하위에 log 폴더가 생성되고 그 안에 날짜별로 로그파일이 생성됩니다.
NLog.config 파일은 실행파일이 있는 경로에 두시면 됩니다.

이상 NLog를 이용한 로깅에 대해 알아봤습니다.