[PYTHON/COMMON] mbox 클래스 : 메일 박스에서 메일 읽기
■ mbox 클래스를 사용해 메일 박스에서 메일을 읽는 방법을 보여준다. ▶ 예제 코드 (PY)
1 2 3 4 5 6 7 |
import mailbox for message in mailbox.mbox("~/mbox"): subject = message["subject"] print(subject) |
■ mbox 클래스를 사용해 메일 박스에서 메일을 읽는 방법을 보여준다. ▶ 예제 코드 (PY)
1 2 3 4 5 6 7 |
import mailbox for message in mailbox.mbox("~/mbox"): subject = message["subject"] print(subject) |
■ EmailValidationBehavior 클래스를 사용해 메일 주소 여부를 검증하는 방법을 보여준다. ▶ MainPage.xaml
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?xml version="1.0" encoding="utf-8" ?> <ContentPage x:Class="TestProject.MainPage" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> <Entry x:Name="entry" HorizontalOptions="Center" VerticalOptions="Center" BackgroundColor="Yellow" WidthRequest="200" Placeholder="메일 주소를 입력해 주시기 바랍니다." /> </ContentPage> |
▶ MainPage.xaml.cs
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 |
using CommunityToolkit.Maui.Behaviors; namespace TestProject; /// <summary> /// 메인 페이지 /// </summary> public partial class MainPage : ContentPage { //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainPage() /// <summary> /// 생성자 /// </summary> public MainPage() { InitializeComponent(); Style validStyle = new Style(typeof(Entry)); validStyle.Setters.Add(new Setter { Property = Entry.TextColorProperty, Value = Colors.Green }); Style invalidStyle = new Style(typeof(Entry)); invalidStyle.Setters.Add(new Setter { Property = Entry.TextColorProperty, Value = Colors.Red }); EmailValidationBehavior behavior = new EmailValidationBehavior { ValidStyle = validStyle, InvalidStyle = invalidStyle, Flags = ValidationFlags.ValidateOnValueChanged }; this.entry.Behaviors.Add(behavior); } #endregion } |
▶ MauiProgram.cs
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 |
using CommunityToolkit.Maui; namespace TestProject; /// <summary> /// MAUI 프로그램 /// </summary> public static class MauiProgram { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Public #region MAUI 앱 생성하기 - CreateMauiApp() /// <summary> /// MAUI 앱 생성하기 /// </summary> /// <returns>MAUI 앱</returns> public static MauiApp CreateMauiApp() { MauiAppBuilder builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .UseMauiCommunityToolkit() .ConfigureFonts ( fontCollection => { fontCollection.AddFont("OpenSans-Regular.ttf" , "OpenSansRegular" ); fontCollection.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); } ); return builder.Build(); } #endregion } |
TestProject.zip
■ EmailValidationBehavior 엘리먼트를 사용해 메일 주소 여부를 검증하는 방법을 보여준다. ▶ MainPage.xaml
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 |
<?xml version="1.0" encoding="utf-8" ?> <ContentPage x:Class="TestProject.MainPage" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"> <ContentPage.Resources> <Style x:Key="ValidEntryStyleKey" TargetType="Entry"> <Setter Property="TextColor" Value="Green" /> </Style> <Style x:Key="InvalidEntryStyleKey" TargetType="Entry"> <Setter Property="TextColor" Value="Red" /> </Style> </ContentPage.Resources> <Entry x:Name="entry" HorizontalOptions="Center" VerticalOptions="Center" BackgroundColor="Yellow" WidthRequest="200" Placeholder="메일 주소를 입력해 주시기 바랍니다."> <Entry.Behaviors> <toolkit:EmailValidationBehavior ValidStyle="{StaticResource ValidEntryStyleKey}" InvalidStyle="{StaticResource InvalidEntryStyleKey}" Flags="ValidateOnValueChanged" /> </Entry.Behaviors> </Entry> </ContentPage> |
▶ MauiProgram.cs
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 |
using CommunityToolkit.Maui; namespace TestProject; /// <summary> /// MAUI 프로그램 /// </summary> public static class MauiProgram { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Public #region MAUI 앱 생성하기 - CreateMauiApp() /// <summary> /// MAUI 앱 생성하기 /// </summary> /// <returns>MAUI 앱</returns> public static MauiApp CreateMauiApp() { MauiAppBuilder builder = MauiApp.CreateBuilder(); builder .UseMauiApp<App>() .UseMauiCommunityToolkit() .ConfigureFonts ( fontCollection => { fontCollection.AddFont("OpenSans-Regular.ttf" , "OpenSansRegular" ); fontCollection.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold"); } ); return builder.Build(); } #endregion } |
TestProject.zip
■ MailAddress 클래스를 사용해 E 메일 주소 여부를 구하는 방법을 보여준다. ▶ Program.cs
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 |
using System.Net.Mail; namespace TestProject; /// <summary> /// 프로그램 /// </summary> class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region E 메일 주소 여부 구하기 - IsEMailAddress( source) /// <summary> /// E 메일 주소 여부 구하기 /// </summary> /// <param name="source">소스 문자열</param> /// <returns>E 메일 주소 여부</returns> private static bool IsEMailAddress(string source) { try { MailAddress mailAddress = new MailAddress(source); return mailAddress.Address == source; } catch { return false; } } #endregion #region 프로그램 시작하기 - Main() /// <summary> /// 프로그램 시작하기 /// </summary> private static void Main() { string source = "icodebroker@naver.com"; Console.WriteLine($"{source} : {IsEMailAddress(source)}"); } #endregion } |
TestProject.zip
■ IEmail 인터페이스의 ComposeAsync 메소드 사용시, 첨부 파일을 추가하는 방법을 보여준다. ▶ 예제 코드 (C#)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
if(Email.Default.IsComposeSupported) { string[] recipientArray = new[] { "john@contoso.com", "jane@contoso.com" }; string subject = "Hello friends!"; string body = "It was great to see you last weekend. I've attached a photo of our adventures together."; EmailMessage message = new EmailMessage { To = new List<string>(recipientArray), Subject = subject, BodyFormat = EmailBodyFormat.PlainText, Body = body }; string filePath = Path.Combine(FileSystem.CacheDirectory, "memories.jpg"); message.Attachments.Add(new EmailAttachment(filePath)); await Email.Default.ComposeAsync(message); } |
■ IEmail 인터페이스의 ComposeAsync 메소드를 사용해 메일을 작성하는 방법을 보여준다. (ANDROID) ▶ Platforms/Android/AndroidManifest.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"> <application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true"></application> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <queries> <intent> <action android:name="android.intent.action.SENDTO" /> <data android:scheme="mailto" /> </intent> </queries> </manifest> |
▶ MainPage.xaml
1 2 3 4 5 6 7 8 9 10 11 |
<?xml version="1.0" encoding="utf-8" ?> <ContentPage x:Class="TestProject.MainPage" xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"> <Button x:Name="composeButton" HorizontalOptions="Center" VerticalOptions="Center" Text="메일 작성" /> </ContentPage> |
▶ MainPage.xaml.cs
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 |
namespace TestProject; /// <summary> /// 메인 페이지 /// </summary> public partial class MainPage : ContentPage { //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - MainPage() /// <summary> /// 생성자 /// </summary> public MainPage() { InitializeComponent(); this.composeButton.Clicked += composeButton_Clicked; } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private #region 메일 작성 버튼 클릭시 처리하기 - composeButton_Clicked(sender, e) /// <summary> /// 메일 작성 버튼 클릭시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private async void composeButton_Clicked(object sender, EventArgs e) { if(Email.Default.IsComposeSupported) { string[] recipientArray = new string[] { "tester@gmail.com" }; string subject = "Hello friends!"; string body = "It was great to see you last weekend."; EmailMessage message = new EmailMessage { To = new List<string>(recipientArray), Subject = subject, BodyFormat = EmailBodyFormat.PlainText, Body = body }; await Email.Default.ComposeAsync(message); } } #endregion } |
TestProject.zip
■ MailItem 인터페이스를 사용해 메일 메시지 헤더를 구하는 방법을 보여준다. ▶ MailItemExtension.cs
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 84 85 86 87 88 89 90 |
using Microsoft.Office.Interop.Outlook; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; namespace TestProject { /// <summary> /// 메일 항목 확장 /// </summary> public static class MailItemExtensions { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// PR_TRANSPORT_MESSAGE_HEADERS /// </summary> private const string PR_TRANSPORT_MESSAGE_HEADERS = "http://schemas.microsoft.com/mapi/proptag/0x007D001F"; /// <summary> /// 정규식 패턴 /// </summary> private const string REGULAR_EXPRESSION_PATTERN = @"^(?<header_key>[-A-Za-z0-9]+)(?<seperator>:[ \t]*)" + "(?<header_value>([^\r\n]|\r\n[ \t]+)*)(?<terminator>\r\n)"; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Public #region 메일 헤더 구하기 - GetMailHeader(mailItem) /// <summary> /// 메일 헤더 구하기 /// </summary> /// <param name="mailItem">메일 항목</param> /// <returns>메일 헤더</returns> public static string GetMailHeader(this MailItem mailItem) { return (string)mailItem.PropertyAccessor.GetProperty(PR_TRANSPORT_MESSAGE_HEADERS); } #endregion #region 헤더 룩업 구하기 - GetHeaderLookup(mailItem) /// <summary> /// 헤더 룩업 구하기 /// </summary> /// <param name="mailItem">메일 항목</param> /// <returns>헤더 룩업</returns> public static ILookup<string, string> GetHeaderLookup(this MailItem mailItem) { string mailHeader = mailItem.GetMailHeader(); IEnumerable<Match> matchEnumerable = Regex.Matches(mailHeader, REGULAR_EXPRESSION_PATTERN, RegexOptions.Multiline).Cast<Match>(); return matchEnumerable.ToLookup(h => h.Groups["header_key"].Value, h => h.Groups["header_value"].Value); } #endregion #region 메일 헤더 값 배열 구하기 - GetMailHeaderValueArray(mailItem, headerName) /// <summary> /// 메일 헤더 값 배열 구하기 /// </summary> /// <param name="mailItem">메일 항목</param> /// <param name="headerName">헤더명</param> /// <returns>메일 헤더 값 배열</returns> public static string[] GetMailHeaderValueArray(this MailItem mailItem, string headerName) { ILookup<string, string> headerLookup = mailItem.GetHeaderLookup(); if(headerLookup.Contains(headerName)) { return headerLookup[headerName].ToArray(); } return new string[0]; } #endregion } } |
▶ CustomAddIn.cs
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 |
using Microsoft.Office.Interop.Outlook; using System; using System.Linq; using System.Windows.Forms; namespace TestProject { /// <summary> /// 커스텀 애드인 /// </summary> public partial class CustomAddIn { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private //////////////////////////////////////////////////////////////////////////////// Event #region 커스텀 애드인 시작시 처리하기 - CustomAddIn_Startup(sender, e) /// <summary> /// 커스텀 애드인 시작시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void CustomAddIn_Startup(object sender, EventArgs e) { MailItem mailItem = Application.Session.Folders[1].Folders["받은 편지함"].Items[1]; string messageID = mailItem.GetMailHeaderValueArray("Message-ID").FirstOrDefault(); MessageBox.Show(messageID); } #endregion #region 커스텀 애드인 셧다운시 처리하기 - CustomAddIn_Shutdown(sender, e) /// <summary> /// 커스텀 애드인 셧다운시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void CustomAddIn_Shutdown(object sender, EventArgs e) { } #endregion //////////////////////////////////////////////////////////////////////////////// Function #region VSTO에서 생성한 코드 /// <summary> /// 디자이너 지원에 필요한 메서드입니다. /// 이 메서드의 내용을 코드 편집기로 수정하지 마세요. /// </summary> private void InternalStartup() { this.Startup += new System.EventHandler(CustomAddIn_Startup ); this.Shutdown += new System.EventHandler(CustomAddIn_Shutdown); } #endregion } } |
TestProject.zip
■ Application 인터페이스의 ItemSend 이벤트에서 메일 발송을 취소하는 방법을 보여준다. ▶ CustomAddIn.cs
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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
using Microsoft.Office.Interop.Outlook; using System; namespace TestProject { /// <summary> /// 커스텀 애드인 /// </summary> public partial class CustomAddIn { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 애플리케이션 /// </summary> private Application application = null; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private //////////////////////////////////////////////////////////////////////////////// Event #region 커스텀 애드인 시작시 처리하기 - CustomAddIn_Startup(sender, e) /// <summary> /// 커스텀 애드인 시작시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void CustomAddIn_Startup(object sender, EventArgs e) { this.application = Application; this.application.ItemSend += application_ItemSend; } #endregion #region 커스텀 애드인 셧다운시 처리하기 - CustomAddIn_Shutdown(sender, e) /// <summary> /// 커스텀 애드인 셧다운시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void CustomAddIn_Shutdown(object sender, EventArgs e) { } #endregion #region 애플리케이션 항목 발송시 처리하기 - application_ItemSend(item, cancel) /// <summary> /// 애플리케이션 항목 발송시 처리하기 /// </summary> /// <param name="item">항목</param> /// <param name="cancel">취소 여부</param> private void application_ItemSend(object item, ref bool cancel) { MailItem mailItem = item as MailItem; if(mailItem != null) { if(!mailItem.Subject.Contains("테스트")) { mailItem.Body += "메일 제목에 \"테스트\" 문자열을 입력해 주시기 바랍니다."; cancel = true; return; } cancel = false; } } #endregion //////////////////////////////////////////////////////////////////////////////// Function #region VSTO에서 생성한 코드 /// <summary> /// 디자이너 지원에 필요한 메서드입니다. /// 이 메서드의 내용을 코드 편집기로 수정하지 마세요. /// </summary> private void InternalStartup() { this.Startup += new System.EventHandler(CustomAddIn_Startup ); this.Shutdown += new System.EventHandler(CustomAddIn_Shutdown); } #endregion } } |
TestProject.zip
■ SmtpClient 클래스의 Send 메소드를 사용해 메일을 보내는 방법을 보여준다. ▶ Program.cs
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 |
using System.Net; using System.Net.Mail; using System.Net.Mime; using System.Text; namespace TestProject { /// <summary> /// 프로그램 /// </summary> class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region 프로그램 시작하기 - Main() /// <summary> /// 프로그램 시작하기 /// </summary> private static void Main() { MailMessage mailMessage = new MailMessage(); mailMessage.From = new MailAddress("icodebroker@naver.com", "icodebroker", Encoding.UTF8); mailMessage.SubjectEncoding = Encoding.UTF8; mailMessage.Subject = "테스트 메일"; mailMessage.BodyEncoding = Encoding.UTF8; mailMessage.Body = "테스트 메일 입니다."; mailMessage.To.Add(new MailAddress("icodebroker@naver.com", "icodebroker", Encoding.UTF8)); Attachment attachment = new Attachment("IMAGE\\sample.png", new ContentType("image/png")); mailMessage.Attachments.Add(attachment); SmtpClient smtpClient = new SmtpClient("smtp.naver.com"); smtpClient.Port = 587; smtpClient.Credentials = new NetworkCredential("userid", "password"); smtpClient.EnableSsl = true; smtpClient.Send(mailMessage); } #endregion } } |
TestProject.zip
■ MailMessage 클래스의 Attachments 속성을 사용해 첨부 파일을 추가하는 방법을 보여준다. ▶ Program.cs
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 |
using System.Net; using System.Net.Mail; using System.Net.Mime; using System.Text; namespace TestProject { /// <summary> /// 프로그램 /// </summary> class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region 프로그램 시작하기 - Main() /// <summary> /// 프로그램 시작하기 /// </summary> private static void Main() { MailMessage mailMessage = new MailMessage(); mailMessage.From = new MailAddress("icodebroker@naver.com", "icodebroker", Encoding.UTF8); mailMessage.SubjectEncoding = Encoding.UTF8; mailMessage.Subject = "테스트 메일"; mailMessage.BodyEncoding = Encoding.UTF8; mailMessage.Body = "테스트 메일 입니다."; mailMessage.To.Add(new MailAddress("icodebroker@naver.com", "icodebroker", Encoding.UTF8)); Attachment attachment = new Attachment("IMAGE\\sample.png", new ContentType("image/png")); mailMessage.Attachments.Add(attachment); SmtpClient smtpClient = new SmtpClient("smtp.naver.com"); smtpClient.Port = 587; smtpClient.Credentials = new NetworkCredential("userid", "password"); smtpClient.EnableSsl = true; smtpClient.Send(mailMessage); } #endregion } } |
TestProject.zip
■ Attachment 인터페이스의 PropertyAccessor 속성을 사용해 첨부 파일 표시 여부를 설정하는 방법을 보여준다. ▶ CustomAddIn.cs
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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
using Microsoft.Office.Interop.Outlook; using System; using System.IO; using System.Reflection; namespace TestProject { /// <summary> /// 커스텀 애드인 /// </summary> public partial class CustomAddIn { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private //////////////////////////////////////////////////////////////////////////////// Event #region 커스텀 애드인 시작시 처리하기 - CustomAddIn_Startup(sender, e) /// <summary> /// 커스텀 애드인 시작시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void CustomAddIn_Startup(object sender, EventArgs e) { #region 설치 디렉토리 경로를 설정한다. Assembly assembly = Assembly.GetExecutingAssembly(); Uri codeBaseURI = new Uri(assembly.CodeBase); string installDirectoryPath = Path.GetDirectoryName(codeBaseURI.LocalPath); #endregion MailItem mailItem = (MailItem)Application.CreateItem(OlItemType.olMailItem); mailItem.Subject = "테스트 메일 입니다."; mailItem.To = "icodebroker@naver.com"; mailItem.BodyFormat = OlBodyFormat.olFormatHTML; mailItem.HTMLBody = @" <html> <head></head> <body> Hello,<br><br> This is a working example of embedding an image unsing C# :<br><br> <img align=""baseline"" border=""1"" hspace=""0"" src=""cid:image0001"" width=""600"" /></img><br><br> Regards,<br>icodebroker </body> </html>"; string imageFilePath1 = Path.Combine(installDirectoryPath, "IMAGE", "sample1.png"); Attachment attachment1 = mailItem.Attachments.Add(imageFilePath1); attachment1.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x370E001F", "image/png"); attachment1.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001F", "image0001"); attachment1.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x7FFE000B", true); // 첨부 파일을 표시하지 않는다. string imageFilePath2 = Path.Combine(installDirectoryPath, "IMAGE", "sample2.png"); Attachment attachment2 = mailItem.Attachments.Add(imageFilePath2); attachment2.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x7FFE000B", false); // 첨부 파일을 표시한다. mailItem.Display(false); } #endregion #region 커스텀 애드인 셧다운시 처리하기 - CustomAddIn_Shutdown(sender, e) /// <summary> /// 커스텀 애드인 셧다운시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void CustomAddIn_Shutdown(object sender, EventArgs e) { } #endregion //////////////////////////////////////////////////////////////////////////////// Function #region VSTO에서 생성한 코드 /// <summary> /// 디자이너 지원에 필요한 메서드입니다. /// 이 메서드의 내용을 코드 편집기로 수정하지 마세요. /// </summary> private void InternalStartup() { this.Startup += new System.EventHandler(CustomAddIn_Startup ); this.Shutdown += new System.EventHandler(CustomAddIn_Shutdown); } #endregion } } |
TestProject.zip
■ MailItem 인터페이스를 사용해 메일 작성시 내장 이미지를 사용하는 방법을 보여준다. ▶ CustomAddIn.cs
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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
using Microsoft.Office.Interop.Outlook; using System; using System.IO; using System.Reflection; namespace TestProject { /// <summary> /// 커스텀 애드인 /// </summary> public partial class CustomAddIn { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Private //////////////////////////////////////////////////////////////////////////////// Event #region 커스텀 애드인 시작시 처리하기 - CustomAddIn_Startup(sender, e) /// <summary> /// 커스텀 애드인 시작시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void CustomAddIn_Startup(object sender, EventArgs e) { #region 설치 디렉토리 경로를 설정한다. Assembly assembly = Assembly.GetExecutingAssembly(); Uri codeBaseURI = new Uri(assembly.CodeBase); string installDirectoryPath = Path.GetDirectoryName(codeBaseURI.LocalPath); #endregion MailItem mailItem = (MailItem)Application.CreateItem(OlItemType.olMailItem); mailItem.Subject = "테스트 메일 입니다."; mailItem.To = "icodebroker@naver.com"; mailItem.BodyFormat = OlBodyFormat.olFormatHTML; mailItem.HTMLBody = @" <html> <head></head> <body> Hello,<br><br> This is a working example of embedding an image unsing C# :<br><br> <img align=""baseline"" border=""1"" hspace=""0"" src=""cid:image0001"" width=""600"" /></img><br><br> Regards,<br>icodebroker </body> </html>"; string imageFilePath = Path.Combine(installDirectoryPath, "IMAGE", "sample.png"); Attachment attachment = mailItem.Attachments.Add(imageFilePath); attachment.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x370E001F", "image/png"); attachment.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001F", "image0001"); // 모든 첨부 파일들을 숨긴다. mailItem.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/id/{00062008-0000-0000-C000-000000000046}/8514000B", true); mailItem.Display(false); } #endregion #region 커스텀 애드인 셧다운시 처리하기 - CustomAddIn_Shutdown(sender, e) /// <summary> /// 커스텀 애드인 셧다운시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void CustomAddIn_Shutdown(object sender, EventArgs e) { } #endregion //////////////////////////////////////////////////////////////////////////////// Function #region VSTO에서 생성한 코드 /// <summary> /// 디자이너 지원에 필요한 메서드입니다. /// 이 메서드의 내용을 코드 편집기로 수정하지 마세요. /// </summary> private void InternalStartup() { this.Startup += new System.EventHandler(CustomAddIn_Startup ); this.Shutdown += new System.EventHandler(CustomAddIn_Shutdown); } #endregion } } |
TestProject.zip
■ MailItem 인터페이스의 PropertyAccessor 속성을 사용해 메시지 ID를 구하는 방법을 보여준다. ▶ 예제 코드 (C#)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
using Microsoft.Office.Interop.Outlook; #region 메시지 ID 구하기 - GetMessageID(mailItem) /// <summary> /// 메시지 ID 구하기 /// </summary> /// <param name="mailItem">메일 항목</param> /// <returns>메시지 ID</returns> public string GetMessageID(MailItem mailItem) { const string PR_INTERNET_MESSAGE_ID_W_TAG = "http://schemas.microsoft.com/mapi/proptag/0x1035001F"; string messageID = mailItem.PropertyAccessor.GetProperty(PR_INTERNET_MESSAGE_ID_W_TAG) as string; return messageID; } #endregion |
■ Process 클래스의 Start 정적 메소드를 사용해 메일 프로그램을 실행하고 새 메일을 작성하는 방법을 보여준다. ▶ 예제 코드 (C#)
1 2 3 4 5 |
using System.Diagnostics; Process.Start("mailto:icodebroker@naver.com?subject=테스트"); |
■ MailItem 인터페이스를 사용해 메일 메시지 헤더를 구하는 방법을 보여준다. ▶ 예제 코드 (C#)
1 2 3 4 5 6 7 8 9 10 11 |
using Microsoft.Office.Interop.Outlook; const string PR_TRANSPORT_MESSAGE_HEADERS = "http://schemas.microsoft.com/mapi/proptag/0x007D001F"; MAPIFolder folder = Application.ActiveExplorer().Session.Folders["icodebroker@naver.com"].Folders["Inbox"]; MailItem mailitem = folder.Items[1]; string messageHeader = (string)mailitem.PropertyAccessor.GetProperty(PR_TRANSPORT_MESSAGE_HEADERS); |
■ MailItem 인터페이스를 사용해 EML 파일을 저장하는 방법을 보여준다. ▶ RibbonContextMenu.xml
1 2 3 4 5 6 7 8 9 10 11 12 |
<?xml version="1.0" encoding="UTF-8"?> <customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui" onLoad="customUI_onLoad"> <contextMenus> <contextMenu idMso="ContextMenuMailItem"> <button id="saveEMLFileButton" label="EML 파일 저장하기" onAction="contextMenu_onAction" /> </contextMenu> </contextMenus> </customUI> |
▶ RibbonContextMenu.cs
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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
using Microsoft.Office.Core; using Microsoft.Office.Interop.Outlook; using System; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Runtime.InteropServices; using System.Windows.Forms; using MimeKit; namespace TestProject { /// <summary> /// 리본 컨텍스트 메뉴 /// </summary> [ComVisible(true)] public class RibbonContextMenu : IRibbonExtensibility { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private #region Field /// <summary> /// 리본 UI /// </summary> private IRibbonUI ribbonUI; #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor ////////////////////////////////////////////////////////////////////////////////////////// Public #region 생성자 - RibbonContextMenu() /// <summary> /// 생성자 /// </summary> public RibbonContextMenu() { } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public //////////////////////////////////////////////////////////////////////////////// Event #region 커스텀 UI 로드시 처리하기 - customUI_onLoad(ribbonUI) /// <summary> /// 커스텀 UI 로드시 처리하기 /// </summary> /// <param name="ribbonUI">리본 UI</param> public void customUI_onLoad(IRibbonUI ribbonUI) { this.ribbonUI = ribbonUI; } #endregion #region 컨텍스트 메뉴 작업시 처리하기 - contextMenu_onAction(ribbonControl) /// <summary> /// 컨텍스트 메뉴 작업시 처리하기 /// </summary> /// <param name="ribbonControl">리본 컨트롤</param> public void contextMenu_onAction(IRibbonControl ribbonControl) { switch(ribbonControl.Id) { case "saveEMLFileButton" : try { dynamic itemCollection = ribbonControl.Context; foreach(dynamic item in itemCollection) { if(item is MailItem mailItem) { SaveEMLFile(mailItem, "d:\\test.eml"); } } } catch(System.Exception exception) { MessageBox.Show($"예외가 발생하였습니다.\r\n{exception.ToString()}"); } break; } } #endregion //////////////////////////////////////////////////////////////////////////////// Function #region (IRibbonExtensibility) 커스텀 UI 구하기 - GetCustomUI(ribbonID) /// <summary> /// 커스텀 UI 구하기 /// </summary> /// <param name="ribbonID">리본 ID</param> /// <returns>커스텀 UI</returns> public string GetCustomUI(string ribbonID) { return ribbonID.Equals("Microsoft.Outlook.Explorer") ? GetResourceText("TestProject.RibbonContextMenu.xml") : null; } #endregion ////////////////////////////////////////////////////////////////////////////////////////// Private //////////////////////////////////////////////////////////////////////////////// Function #region 리소스 텍스트 구하기 - GetResourceText(resourceName) /// <summary> /// 리소스 텍스트 구하기 /// </summary> /// <param name="resourceName">리소스명</param> /// <returns>리소스 텍스트</returns> private static string GetResourceText(string resourceName) { Assembly assembly = Assembly.GetExecutingAssembly(); string[] resourceNameArray = assembly.GetManifestResourceNames(); int count = resourceNameArray.Length; for(int i = 0; i < count; ++i) { if(string.Compare(resourceName, resourceNameArray[i], StringComparison.OrdinalIgnoreCase) == 0) { using(StreamReader reader = new StreamReader(assembly.GetManifestResourceStream(resourceNameArray[i]))) { if(reader != null) { return reader.ReadToEnd(); } } } } return null; } #endregion #region EML 파일 저장하기 - SaveEMLFile(mailItem, filePath) /// <summary> /// EML 파일 저장하기 /// </summary> /// <param name="mailItem">메일 항목</param> /// <param name="filePath">파일 경로</param> private void SaveEMLFile(MailItem mailItem, string filePath) { System.Net.Mail.MailMessage mailMessage = new System.Net.Mail.MailMessage(); mailMessage.Subject = mailItem.Subject; mailMessage.From = new System.Net.Mail.MailAddress(mailItem.Sender.Address, mailItem.Sender.Name); mailMessage.IsBodyHtml = mailItem.BodyFormat == OlBodyFormat.olFormatHTML; mailMessage.Body = mailItem.BodyFormat == OlBodyFormat.olFormatHTML ? mailItem.HTMLBody : mailItem.Body; foreach(Recipient recipient in mailItem.Recipients) { if(recipient.Type == (int)OlMailRecipientType.olTo) { mailMessage.To.Add(new System.Net.Mail.MailAddress(recipient.Address, recipient.Name)); } else if(recipient.Type == (int)OlMailRecipientType.olCC) { mailMessage.CC.Add(new System.Net.Mail.MailAddress(recipient.Address, recipient.Name)); } else if(recipient.Type == (int)OlMailRecipientType.olBCC) { mailMessage.Bcc.Add(new System.Net.Mail.MailAddress(recipient.Address, recipient.Name)); } } List<string> temporaryDirectoryPathList = new List<string>(); try { foreach(Attachment attachment in mailItem.Attachments) { #region 임시 디렉토리 경로를 설정한다. string temporaryDirectoryPath = Path.Combine(Path.GetTempPath(), "Temp", Guid.NewGuid().ToString()); #endregion #region 임시 디렉토리 경로를 생성한다. if(!Directory.Exists(temporaryDirectoryPath)) { Directory.CreateDirectory(temporaryDirectoryPath); } #endregion temporaryDirectoryPathList.Add(temporaryDirectoryPath); #region 첨부 파일을 저장한다. string attachmentFilePath = Path.Combine(temporaryDirectoryPath, attachment.FileName); attachment.SaveAsFile(attachmentFilePath); #endregion #region MIME 타입을 설정한다. string fileExtension = Path.GetExtension(attachment.FileName); string mimeType = MIMETypeHelper.GetMIMEType(fileExtension); #endregion mailMessage.Attachments.Add(new System.Net.Mail.Attachment(attachmentFilePath, mimeType)); } MimeMessage mimeMessage = (MimeMessage)mailMessage; mimeMessage.Date = mailItem.CreationTime; mimeMessage.WriteTo(filePath); mailMessage.Dispose(); } finally { foreach(string path in temporaryDirectoryPathList) { if(Directory.Exists(path)) { Directory.Delete(path, true); } } } } #endregion } } |
▶ CustomAddIn.cs
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 |
using Microsoft.Office.Core; using System; namespace TestProject { /// <summary> /// 커스텀 애드인 /// </summary> public partial class CustomAddIn { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Protected #region 리본 확장성 객체 생성하기 - CreateRibbonExtensibilityObject() /// <summary> /// 리본 확장성 객체 생성하기 /// </summary> /// <returns>리본 확장성 인터페이스 객체</returns> protected override IRibbonExtensibility CreateRibbonExtensibilityObject() { return new RibbonContextMenu(); } #endregion ////////////////////////////////////////////////////////////////////////////////////////// Private #region 커스텀 애드인 시작시 처리하기 - CustomAddIn_Startup(sender, e) /// <summary> /// 커스텀 애드인 시작시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void CustomAddIn_Startup(object sender, EventArgs e) { } #endregion #region 커스텀 애드인 셧다운시 처리하기 - CustomAddIn_Shutdown(sender, e) /// <summary> /// 커스텀 애드인 셧다운시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void CustomAddIn_Shutdown(object sender, EventArgs e) { } #endregion #region VSTO에서 생성한 코드 /// <summary> /// 디자이너 지원에 필요한 메서드입니다. /// 이 메서드의 내용을 코드 편집기로 수정하지 마세요. /// </summary> private void InternalStartup() { this.Startup += new EventHandler(CustomAddIn_Startup ); this.Shutdown += new EventHandler(CustomAddIn_Shutdown); } #endregion } } |
TestProject.zip
■ MimeMessage 클래스의 WriteTo 메소드를 사용해 EML 파일을 저장하는 방법을 보여준다. ▶ Program.cs
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 |
using System; using System.Net.Mail; using MimeKit; namespace TestProject { /// <summary> /// 프로그램 /// </summary> class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region 프로그램 시작하기 - Main() /// <summary> /// 프로그램 시작하기 /// </summary> private static void Main() { MailMessage mailMessage = new MailMessage(); mailMessage.Subject = "테스트 메일"; mailMessage.From = new MailAddress("sender@domain.com"); mailMessage.Body = "테스트 메일 입니다."; mailMessage.To.Add(new MailAddress("receiver@domain.com")); MimeMessage mimeMessage = (MimeMessage)mailMessage; mimeMessage.Date = new DateTimeOffset(new DateTime(2021, 1, 1, 13, 0, 0)); mimeMessage.WriteTo(@"d:\test.eml"); } #endregion } } |
TestProject.zip
■ SmtpClient 클래스의 DeliveryMethod/PickupDirectoryLocation 속성을 사용해 EML 파일을 저장하는 방법을 보여준다. (기능 개선) ▶ test.eml (생성 파일)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
-Sender: sender@domain.com X-Receiver: receiver@domain.com MIME-Version: 1.0 From: sender@domain.com To: receiver@domain.com Date: 6 Aug 2021 20:41:09 +0900 Subject: =?utf-8?B?7YWM7Iqk7Yq4IOuplOydvA==?= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: base64 7YWM7Iqk7Yq4IOuplOydvCDsnoXri4jri6Qu---------------------------------------------------------------------------------------------------- ▶ MailMessageExtension.cs |
using System; using System.IO;
■ SmtpClient 클래스의 DeliveryMethod/PickupDirectoryLocation 속성을 사용해 EML 파일을 저장하는 방법을 보여준다. ▶ Program.cs
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 |
using System.Net.Mail; namespace TestProject { /// <summary> /// 프로그램 /// </summary> class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region 프로그램 시작하기 - Main() /// <summary> /// 프로그램 시작하기 /// </summary> private static void Main() { MailMessage mailMessage = new MailMessage(); mailMessage.Subject = "테스트 메일"; mailMessage.From = new MailAddress("sender@domain.com"); mailMessage.Body = "테스트 메일 입니다."; mailMessage.To.Add(new MailAddress("receiver@domain.com")); SmtpClient smtpClient = new SmtpClient("dummy"); smtpClient.DeliveryMethod = SmtpDeliveryMethod.SpecifiedPickupDirectory; smtpClient.PickupDirectoryLocation = @"d:\\"; smtpClient.Send(mailMessage); } #endregion } } |
TestProject.zip
■ MailMessage 클래스를 사용해 EML 파일을 저장하는 방법을 보여준다. ▶ test.eml (생성 파일)
1 2 3 4 5 6 7 8 9 10 11 12 13 |
-Sender: sender@domain.com X-Receiver: receiver@domain.com MIME-Version: 1.0 From: sender@domain.com To: receiver@domain.com Date: 6 Aug 2021 20:41:09 +0900 Subject: =?utf-8?B?7YWM7Iqk7Yq4IOuplOydvA==?= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: base64 7YWM7Iqk7Yq4IOuplOydvCDsnoXri4jri6Qu |
▶ MailMessageExtension.cs
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 |
using System; using System.IO; using System.Net.Mail; using System.Reflection; namespace TestProject { /// <summary> /// 메일 메시지 확장 /// </summary> public static class MailMessageExtension { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Public #region 저장하기 - Save(mailMessage, filePath) /// <summary> /// 저장하기 /// </summary> /// <param name="mailMessage">메일 메시지</param> /// <param name="filePath">파일 경로</param> public static void Save(this MailMessage mailMessage, string filePath) { Assembly assembly = typeof(SmtpClient).Assembly; Type mailWriterType = assembly.GetType("System.Net.Mail.MailWriter"); using(FileStream fileStream = new FileStream(filePath, FileMode.Create)) { ConstructorInfo mailWriterContructor = mailWriterType.GetConstructor ( BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[] { typeof(Stream) }, null ); object mailWriter = mailWriterContructor.Invoke(new object[] { fileStream }); MethodInfo sendMethodInfo = typeof(MailMessage).GetMethod ( "Send", BindingFlags.Instance | BindingFlags.NonPublic ); sendMethodInfo.Invoke ( mailMessage, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { mailWriter, true }, null ); MethodInfo closeMethodInfo = mailWriter.GetType().GetMethod ( "Close", BindingFlags.Instance | BindingFlags.NonPublic ); closeMethodInfo.Invoke ( mailWriter, BindingFlags.Instance | BindingFlags.NonPublic, null, new object[] { }, null ); } } #endregion } } |
▶ Program.cs
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 |
using System.Net.Mail; namespace TestProject { /// <summary> /// 프로그램 /// </summary> class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region 프로그램 시작하기 - Main() /// <summary> /// 프로그램 시작하기 /// </summary> private static void Main() { MailMessage mailMessage = new MailMessage(); mailMessage.Subject = "테스트 메일"; mailMessage.From = new MailAddress("sender@domain.com"); mailMessage.Body = "테스트 메일 입니다."; mailMessage.To.Add(new MailAddress("receiver@domain.com")); mailMessage.Save(@"d:\test.eml"); } #endregion } } |
TestProject.zip test.zip
■ MAPIFolderEvents_12_Event 인터페이스의 BeforeFolderMove/BeforeItemMove 이벤트를 사용해 폴더/메일 삭제/이동을 방지하는 방법을 보여준다. (기능 개선) ▶ ConstantHelper.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
namespace TestProject { /// <summary> /// 상수 헬퍼 /// </summary> public static class ConstantHelper { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Public #region Field /// <summary> /// Sales Force 폴더명 /// </summary> public static readonly string SalesForceFolderName = "Sales Force"; #endregion } } |
▶ SessionExtensions.cs
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 |
using Microsoft.Office.Interop.Outlook; namespace TestProject { /// <summary> /// 세션 확장 /// </summary> public static class SessionExtensions { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Public #region Sales Force 폴더 생성하기 - CreatSalesForceFolders(session) /// <summary> /// Sales Force 폴더 생성하기 /// </summary> /// <param name="session">세션</param> public static void CreatSalesForceFolders(this NameSpace session) { foreach(Folder rootFolder in session.Folders) { if(!rootFolder.HasFolder(ConstantHelper.SalesForceFolderName)) { rootFolder.AddFolder(ConstantHelper.SalesForceFolderName); } } } #endregion } } |
▶ MAPIFolderExtensions.cs
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 |
using Microsoft.Office.Interop.Outlook; namespace TestProject { /// <summary> /// MAPI 폴더 확장 /// </summary> public static class MAPIFolderExtensions { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Public #region 폴더 소유 여부 구하기 - HasFolder(rootFolder, targetFolderName) /// <summary> /// 폴더 소유 여부 구하기 /// </summary> /// <param name="rootFolder">루트 폴더</param> /// <param name="targetFolderName">타겟 폴더명</param> /// <returns>폴더 소유 여부</returns> public static bool HasFolder(this MAPIFolder rootFolder, string targetFolderName) { foreach(Folder folder in rootFolder.Folders) { if(folder.Name == targetFolderName) { return true; } } return false; } #endregion #region 폴더 구하기 - GetFolder(rootFolder, targetFolderName) /// <summary> /// 폴더 구하기 /// </summary> /// <param name="rootFolder">루트 폴더</param> /// <param name="targetFolderName">타겟 폴더명</param> /// <returns>폴더</returns> public static Folder GetFolder(this MAPIFolder rootFolder, string targetFolderName) { foreach(Folder folder in rootFolder.Folders) { if(folder.Name == targetFolderName) { return folder; } } return null; } #endregion #region 폴더 추가하기 - AddFolder(parentFolder, folderName) /// <summary> /// 폴더 추가하기 /// </summary> /// <param name="parentFolder">부모 폴더</param> /// <param name="folderName">폴더명</param> /// <returns>MAPI 폴더</returns> public static MAPIFolder AddFolder(this MAPIFolder parentFolder, string folderName) { MAPIFolder folder = parentFolder.Folders.Add(folderName, OlDefaultFolders.olFolderInbox); return folder; } #endregion } } |
■ EncodingFinder 클래스의 AddMapping 정적 메소드를 사용해 커스텀 인코딩을 추가하는 방법을 보여준다. ▶ Program.cs
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 |
using System.Text; using OpenPop.Mime.Decode; namespace TestProject { /// <summary> /// 프로그램 /// </summary> class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region 커스텀 폴백 디코더 처리하기 - CustomFallbackDecoder(characterSet) /// <summary> /// 커스텀 폴백 디코더 처리하기 /// </summary> /// <param name="characterSet">문자 세트</param> /// <returns>인코딩</returns> private static Encoding CustomFallbackDecoder(string characterSet) { if(characterSet.StartsWith("foo")) { return Encoding.ASCII; } return Encoding.UTF8; } #endregion #region 커스텀 인코딩 추가하기 - AddCustomEncoding(customEncoding) /// <summary> /// 커스텀 인코딩 추가하기 /// </summary> /// <param name="customEncoding">커스텀 인코딩</param> private static void AddCustomEncoding(Encoding customEncoding) { EncodingFinder.AddMapping("iso-9999-9" , Encoding.UTF8 ); EncodingFinder.AddMapping("specialEncoding", customEncoding); EncodingFinder.FallbackDecoder = CustomFallbackDecoder; } #endregion #region 프로그램 시작하기 - Main() /// <summary> /// 프로그램 시작하기 /// </summary> private static void Main() { AddCustomEncoding(Encoding.Unicode); } #endregion } } |
TestProject.zip
■ Pop3Client 클래스의 Connect 메소드를 사용해 서버 인증서를 검증하는 방법을 보여준다. ▶ Program.cs
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 |
using System.Net.Security; using System.Security.Cryptography.X509Certificates; using OpenPop.Pop3; namespace TestProject { /// <summary> /// 프로그램 /// </summary> class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region 원격 인증서 검증 콜백 처리하기 - RemoteCertificateValidationCallback(sender, certificate, chain, sslpolicyerrors) /// <summary> /// 원격 인증서 검증 콜백 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="certificate">X.509 인증서</param> /// <param name="chain">X.509 체인</param> /// <param name="sslpolicyerrors">SSL 정책 에러</param> /// <returns>처리 결과</returns> private static bool RemoteCertificateValidationCallback ( object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors ) { // SSLPolicyErrors가 있는지 확인해야 하지만 여기서는 단순히 인증서가 정상이라고 말하고 신뢰한다. return true; } #endregion #region SSL 인증서 체크하기 - CheckSSLCertificate(hostName, port, timeout) /// <summary> /// SSL 인증서 체크하기 /// </summary> /// <param name="hostName">호스트명</param> /// <param name="port">포트</param> /// <param name="timeout">타임아웃</param> private static void CheckSSLCertificate(string hostName, int port, int timeout) { using(Pop3Client client = new Pop3Client()) { client.Connect(hostName, port, true, timeout, timeout, RemoteCertificateValidationCallback); } } #endregion #region 프로그램 시작하기 - Main() /// <summary> /// 프로그램 시작하기 /// </summary> private static void Main() { string hostName = "pop.naver.com"; int port = 995; CheckSSLCertificate(hostName, port, 3000); } #endregion } } |
TestProject.zip
■ IAnswerMessageTraverser<T> 인터페이스를 사용해 메시지 파트 계층을 탐색하는 방법을 보여준다. ▶ MessageNode.cs
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 |
using System.Collections.Generic; using OpenPop.Mime; namespace TestProject { /// <summary> /// 메시지 노드 /// </summary> public class MessageNode { //////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public #region 노드명 - NodeName /// <summary> /// 노드명 /// </summary> public string NodeName { get; set; } #endregion #region 메시지 파트 - MessagePart /// <summary> /// 메시지 파트 /// </summary> public MessagePart MessagePart { get; set; } #endregion #region 자식 노드 리스트 - ChildNodeList /// <summary> /// 자식 노드 리스트 /// </summary> public List<MessageNode> ChildNodeList { get; set; } = new List<MessageNode>(); #endregion } } |
▶ MessageTraverser.cs
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 |
using System; using OpenPop.Mime; using OpenPop.Mime.Traverse; namespace TestProject { /// <summary> /// 메시지 횡단자 /// </summary> public class MessageTraverser : IAnswerMessageTraverser<MessageNode> { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public #region 메시지 파트 방문하기 - VisitMessagePart(messagePart) /// <summary> /// 메시지 파트 방문하기 /// </summary> /// <param name="messagePart">메시지 파트</param> /// <returns>메시지 노드</returns> public MessageNode VisitMessagePart(MessagePart messagePart) { if(messagePart == null) { throw new ArgumentNullException("messagePart"); } MessageNode node = new MessageNode(); node.NodeName = messagePart.ContentType.MediaType; node.MessagePart = messagePart; if(messagePart.IsMultiPart) { for(int i = 0; i< messagePart.MessageParts.Count; i++) { MessageNode childNode = VisitMessagePart(messagePart.MessageParts[i]); node.ChildNodeList.Add(childNode); } } return node; } #endregion #region 메시지 방문하기 - VisitMessage(message) /// <summary> /// 메시지 방문하기 /// </summary> /// <param name="message">메시지</param> /// <returns>메시지 노드</returns> public MessageNode VisitMessage(Message message) { if(message == null) { throw new ArgumentNullException("message"); } MessageNode childNode = VisitMessagePart(message.MessagePart); MessageNode node = new MessageNode(); node.NodeName = message.Headers.Subject; node.MessagePart = message.MessagePart; node.ChildNodeList.Add(childNode); return node; } #endregion } } |
▶ Program.cs
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 |
using System; using OpenPop.Mime; using OpenPop.Pop3; namespace TestProject { /// <summary> /// 프로그램 /// </summary> class Program { //////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Static //////////////////////////////////////////////////////////////////////////////// Private #region 메시지 노드 쓰기 - WriteMessageNode(messageNode, nodeLevel) /// <summary> /// 메시지 노드 쓰기 /// </summary> /// <param name="messageNode">메시지 노드</param> /// <param name="nodeLevel">노드 레벨</param> private static void WriteMessageNode(MessageNode messageNode, int nodeLevel = 0) { Console.WriteLine($"{" ".PadRight(nodeLevel * 4)}{messageNode.NodeName}"); foreach(MessageNode childNode in messageNode.ChildNodeList) { WriteMessageNode(childNode, nodeLevel + 1); } } #endregion #region 프로그램 시작하기 - Main() /// <summary> /// 프로그램 시작하기 /// </summary> private static void Main() { string hostName = "pop.naver.com"; int port = 995; bool useSSL = true; string userName = "tester"; string password = "1234"; using(Pop3Client client = new Pop3Client()) { client.Connect(hostName, port, useSSL); client.Authenticate(userName, password); int messageCount = client.GetMessageCount(); for(int i = 1; i <= messageCount; i++) { Message message = client.GetMessage(i); MessageTraverser traverser = new MessageTraverser(); MessageNode node = traverser.VisitMessage(message); WriteMessageNode(node); Console.WriteLine(); } } } #endregion } } |
TestProject.zip
■ Pop3Client 클래스의 DeleteMessage 메소드를 사용해 메일을 삭제하는 방법을 보여준다. ▶ 예제 코드 (C#)
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 |
using OpenPop.Pop3; #region 메일 삭제하기 - DeleteMail(client, messageID) /// <summary> /// 메일 삭제하기 /// </summary> /// <param name="client">클라이언트</param> /// <param name="messageID">메시지 ID</param> /// <returns>처리 결과</returns> public bool DeleteMail(Pop3Client client, string messageID) { int messageCount = client.GetMessageCount(); for(int i = messageCount; i > 0; i--) { if(client.GetMessageHeaders(i).MessageId == messageID) { client.DeleteMessage(i); return true; } } return false; } #endregion |