using Microsoft.Exchange.WebServices.Data;
using Newtonsoft.Json.Linq;
using RestApi.Controllers;
using RestApi.Models;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
using System.Windows.Forms;
namespace RestApi.Algorithms
{
public class EwsHelper : BaseController
{
public ExchangeService mEws;
#region Ews 권한 획득
public ExchangeService GetAccessToken(string userEmail)
{
if (mEws == null)
{
try
{
string ewsUri = ConfigurationManager.AppSettings["EWSUri"];
string DomainName = ConfigurationManager.AppSettings["DomainName"];
//string AdminID = ConfigurationManager.AppSettings["AdminID"];
//string AdminPwd = ConfigurationManager.AppSettings["AdminPwd"];
mEws = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
//mEws.Credentials = new WebCredentials(emailAddr, userPw, DomainNm);
mEws.UseDefaultCredentials = true;
mEws.PreAuthenticate = true;
mEws.Url = new Uri(ewsUri);
mEws.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, userEmail);
mEws.HttpHeaders.Add("X-AnchorMailbox", userEmail);
}
catch (Exception ex)
{
ComHelper.WriteErrorLog(ex, userEmail, "E_R021");
}
}
return mEws;
}
#endregion
#region 일정 등록
public MdResultT1
CreateEvent(string userEmail, string subject, string cttsType, string ctts, DateTime startDate, DateTime endDate, string timeZone
, string location, string recName, int reminderMinutes, string sensitivity, string importance, JArray attendees, bool isDetail, HttpRequestMessage request, string bodyData, string tmpLog)
{
GetAccessToken(userEmail);
MdResultT1 rstAt = new MdResultT1(false, "");
string scheduleID = "";
if (mEws == null)
{
rstAt.message = "Ews 권한획득에 실패하였습니다.";
ComHelper.WriteErrorLog(new Exception(), request, bodyData, "E_R022");
return rstAt;
}
StringBuilder addLog = new StringBuilder(2000);
try
{
Appointment appointment = new Appointment(mEws)
{
Subject = subject,
Body = new MessageBody((BodyType)Enum.Parse(typeof(BodyType), cttsType, true), ctts),
Start = startDate,
End = endDate,
Location = location,
ReminderMinutesBeforeStart = reminderMinutes,
Sensitivity = (Sensitivity)Enum.Parse(typeof(Sensitivity), sensitivity, true),
Importance = (Importance)Enum.Parse(typeof(Importance), importance, true)
};
if (attendees != null && attendees.Count > 0)
{
try
{
foreach (JObject item in attendees)
{
string atdNm = item["attedName"].ToString();
string atdEmail = item["attedEmail"].ToString();
if (item["attedType"].ToString() == "required")
{
appointment.RequiredAttendees.Add(new Attendee(atdNm, atdEmail));
}
else
{
appointment.OptionalAttendees.Add(new Attendee(atdNm, atdEmail));
}
addLog.Append($"{Environment.NewLine} name:{atdNm}, email:{atdEmail}, type:{item["attedType"].ToString()}");
}
}
catch (Exception ex1)
{
ComHelper.WriteErrorLog(ex1, request, bodyData, "E_R023");
rstAt.message = "참석자 정보 필수값이 없습니다. 확인하여 주세요.[EWS].";
return rstAt;
}
}
appointment.Save(SendInvitationsMode.SendToAllAndSaveCopy);
string evtID = appointment.Id.UniqueId;
// 회의실 이름을 Resources 컬렉션에 추가 ExtendedProperty로 ResourceName 저장
ExtendedPropertyDefinition resourceNameProp = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, "ResourceName", MapiPropertyType.String);
PropertySet propSet = new PropertySet(BasePropertySet.FirstClassProperties);
propSet.Add(resourceNameProp);
Appointment savedAppt = Appointment.Bind(mEws, evtID, propSet);
if (savedAppt.ExtendedProperties != null && savedAppt.ExtendedProperties.Any(p => p.PropertyDefinition.Equals(resourceNameProp)))
{
savedAppt.RemoveExtendedProperty(resourceNameProp);
savedAppt.SetExtendedProperty(resourceNameProp, recName);
savedAppt.Update(ConflictResolutionMode.AlwaysOverwrite);
}
else if (string.IsNullOrWhiteSpace(recName) == false)
{
savedAppt.SetExtendedProperty(resourceNameProp, recName);
savedAppt.Update(ConflictResolutionMode.AlwaysOverwrite);
}
rstAt.success = true;
rstAt.key = evtID;// 이벤트 ID 가져오기
if (isDetail)
{
MdResultT1 tmpAt = GetEventDetail(userEmail, rstAt.key, timeZone, request, bodyData);
rstAt.data = tmpAt.data;
}
}
catch (Exception ex2)
{
rstAt.message = "Ews 일정등록에 실패하였습니다.";
rstAt.exmsg = ex2.Message;
ComHelper.WriteErrorLog(ex2, request, bodyData, "E_R024" + addLog);
}
finally
{
string strLog = $"userEmail:{userEmail}{Environment.NewLine}subject:{subject}{Environment.NewLine}cttsType:{cttsType}{Environment.NewLine}location:{location}{Environment.NewLine}{tmpLog}{Environment.NewLine}scheduleID : {scheduleID}";
ComHelper.WriteTextLog(request, bodyData, strLog, "");
}
return rstAt;
}
#endregion
#region 일정 수정
public MdResultT1 UpdateEvent(string userEmail, string evtID, string subject, string cttsType, string ctts, DateTime startDate, DateTime endDate, string timeZone,
string location, string recName, int reminderMinutes, string sensitivity, string importance, JArray attendees, bool isDetail, HttpRequestMessage request, string bodyData, string tmpLog)
{
string strLog = $"evtID:{evtID}{Environment.NewLine}userEmail:{userEmail}{Environment.NewLine}subject:{subject}{Environment.NewLine}cttsType:{cttsType}{Environment.NewLine}location:{location}{Environment.NewLine}" + tmpLog;
ComHelper.WriteTextLog(request, bodyData, strLog, "");
GetAccessToken(userEmail);
MdResultT1 rstAt = new MdResultT1(false, "");
if (mEws == null)
{
rstAt.message = "Ews 권한획득에 실패하였습니다.";
return rstAt;
}
try
{
PropertySet props = new PropertySet(
BasePropertySet.FirstClassProperties,
AppointmentSchema.RequiredAttendees,
AppointmentSchema.OptionalAttendees
);
// 3. Item 바인딩
Appointment appointment = Appointment.Bind(mEws, new ItemId(evtID), props);
// 4. 기본 속성 업데이트
appointment.Subject = subject;
appointment.Body = new MessageBody(
(BodyType)Enum.Parse(typeof(BodyType), cttsType, true),
ctts
);
appointment.Start = startDate;
appointment.End = endDate;
appointment.Location = location;
appointment.ReminderMinutesBeforeStart = reminderMinutes;
appointment.Sensitivity = (Sensitivity)Enum.Parse(typeof(Sensitivity), sensitivity, true);
appointment.Importance = (Importance)Enum.Parse(typeof(Importance), importance, true);
appointment.RequiredAttendees.Clear();
appointment.OptionalAttendees.Clear();
// 6. 새 참석자 추가
if (attendees != null && attendees.Count > 0)
{
try
{
foreach (JObject item in attendees)
{
string atdNm = item["attedName"].ToString();
string atdEmail = item["attedEmail"].ToString();
if (item["attedType"].ToString() == "required")
appointment.RequiredAttendees.Add(new Attendee(atdNm, atdEmail));
else
appointment.OptionalAttendees.Add(new Attendee(atdNm, atdEmail));
}
}
catch (Exception ex1)
{
ComHelper.WriteErrorLog(ex1, request, bodyData, "E_R025");
rstAt.message = "참석자 정보 필수값이 없습니다. 확인하여 주세요.[EWS]";
return rstAt;
}
}
// 7. 업데이트 수행
appointment.Update(
ConflictResolutionMode.AutoResolve,
SendInvitationsOrCancellationsMode.SendToAllAndSaveCopy
);
// 회의실 이름을 Resources 컬렉션에 추가 ExtendedProperty로 ResourceName 저장
ExtendedPropertyDefinition resourceNameProp = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, "ResourceName", MapiPropertyType.String);
PropertySet propSet = new PropertySet(BasePropertySet.FirstClassProperties);
propSet.Add(resourceNameProp);
Appointment savedAppt = Appointment.Bind(mEws, evtID, propSet);
if (savedAppt.ExtendedProperties != null && savedAppt.ExtendedProperties.Any(p => p.PropertyDefinition.Equals(resourceNameProp)))
{
savedAppt.RemoveExtendedProperty(resourceNameProp);
savedAppt.SetExtendedProperty(resourceNameProp, recName);
savedAppt.Update(ConflictResolutionMode.AlwaysOverwrite);
}
else if(string.IsNullOrWhiteSpace(recName) == false)
{
savedAppt.SetExtendedProperty(resourceNameProp, recName);
savedAppt.Update(ConflictResolutionMode.AlwaysOverwrite);
}
// 8. 결과 처리
rstAt.success = true;
rstAt.key = appointment.Id.UniqueId;
if (isDetail)
{
MdResultT1 tmpAt = GetEventDetail(userEmail, rstAt.key, timeZone, request, bodyData);
rstAt.data = tmpAt.data;
}
}
catch (Exception ex2)
{
ComHelper.WriteErrorLog(ex2, request, bodyData, "E_R026");
rstAt.message = "Ews 일정수정에 실패하였습니다.";
rstAt.exmsg = ex2.Message;
}
return rstAt;
}
#endregion
#region 일정 삭제
public MdResultBase DeleteEvent(string userEmail, string evtID, HttpRequestMessage request, string bodyData, string tmpLog)
{
ComHelper.WriteTextLog(request, bodyData, $"userEmail:{userEmail}, {tmpLog}", evtID);
GetAccessToken(userEmail);
MdResultBase rBase = new MdResultBase(false, "", "");
if (mEws == null)
{
ComHelper.WriteErrorLog(new Exception(), request, bodyData, $"E_R027 → evtID : {evtID}");
return rBase.SetRst(false, "Ews 권한획득에 실패하였습니다.", "");
}
try
{
Appointment appointment = Appointment.Bind(mEws, new ItemId(evtID));
appointment.Delete(DeleteMode.HardDelete, SendCancellationsMode.SendToAllAndSaveCopy);
rBase.SetRst(true, "일정 삭제가 완료 되었습니다.", "SSS");
}
catch (Exception ex)
{
rBase.SetRst(false, "Ews 일정삭제에 실패하였습니다.", "E00", ex.Message);
ComHelper.WriteErrorLog(ex, request, bodyData, $"E_R028 → evtID : {evtID}");
}
return rBase;
}
#endregion
#region 일정 리스트
public MdResultT1> GetEventList(string userEmail, DateTime startDate, DateTime endDate, string timeZone, HttpRequestMessage request, string bodyData)
{
GetAccessToken(userEmail);
MdResultT1> rstAt = new MdResultT1>(false, "");
List rstList = new List();
if (mEws == null)
{
rstAt.message = "Ews 권한획득에 실패하였습니다.";
ComHelper.WriteErrorLog(new Exception(), request, bodyData, "E_R029");
return rstAt;
}
try
{
CalendarView calendarView = new CalendarView(startDate, endDate, 1000)
{
//PropertySet = new PropertySet(BasePropertySet.FirstClassProperties)
PropertySet = new PropertySet(
BasePropertySet.FirstClassProperties, AppointmentSchema.Subject, AppointmentSchema.Start, AppointmentSchema.End, AppointmentSchema.Location, AppointmentSchema.Organizer
, AppointmentSchema.Importance, AppointmentSchema.Sensitivity, AppointmentSchema.AppointmentState)
};
ExtendedPropertyDefinition resourceNameProp = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, "ResourceName", MapiPropertyType.String);
calendarView.PropertySet.Add(resourceNameProp);
FindItemsResults appointments = mEws.FindAppointments(WellKnownFolderName.Calendar, calendarView);
JArray eventList = new JArray();
foreach (Appointment appt in appointments)
{
// 취소된 일정은 건너뛰기
if (appt.AppointmentState == 7)
continue;
/* 개별 바인딩해서 참석자 등 상세 속성 로드 */
PropertySet bindProps = new PropertySet(BasePropertySet.FirstClassProperties, AppointmentSchema.Body, AppointmentSchema.RequiredAttendees, AppointmentSchema.OptionalAttendees);
bindProps.Add(resourceNameProp);
Appointment fullAppt = Appointment.Bind(mEws, appt.Id, bindProps);
string wName = ComHelper.NullToEmpty(appt.Organizer?.Name);
string uName = wName;
string wEmail = ComHelper.NullToEmpty(appt.Organizer?.Address);
if (wEmail.Contains("/O=")) // X500 주소인 경우
{
// ExchangeResolveName 사용
NameResolutionCollection nameRes = mEws.ResolveName(wEmail, ResolveNameSearchLocation.DirectoryOnly, true);
if (nameRes.Count > 0)
{
wEmail = nameRes[0].Mailbox.Address;
}
}
string uEmail = wEmail;
MdCldData tmpList = new MdCldData();
tmpList.schKey = ComHelper.NullToEmpty(appt.Id.UniqueId);
tmpList.writeName = wName;
tmpList.writeEmail = wEmail;
tmpList.subject = ComHelper.NullToEmpty(appt.Subject);
tmpList.startDate = DateTime.Parse(appt.Start.ToString("yyyy-MM-ddTHH:mm:ss"));
tmpList.startZone = ComHelper.NullToEmpty(appt.Start.Kind);
tmpList.endDate = DateTime.Parse(appt.End.ToString("yyyy-MM-ddTHH:mm:ss"));
tmpList.endZone = ComHelper.NullToEmpty(appt.End.Kind);
tmpList.location = ComHelper.NullToEmpty(appt.Location); // 장소
tmpList.Importance = ComHelper.NullToEmpty(appt.Importance);
tmpList.contentType = ComHelper.NullToEmpty(fullAppt.Body.BodyType);
tmpList.content = ComHelper.NullToEmpty(fullAppt.Body.Text);
tmpList.sensitivity = ComHelper.NullToEmpty(appt.Sensitivity);
tmpList.repeatedYn = "N";
// 참석자 정보 추가
JArray attendees = new JArray();
foreach (Attendee atd in fullAppt.RequiredAttendees)
{
string tmpEmail = atd.Address;
string tmpName = atd.Name;
MdCldAttendee mdAttendees = new MdCldAttendee
{
attedEmail = tmpEmail,
attedName = tmpName,
attedType = "required"
};
tmpList.attendees.Add(mdAttendees);
if (userEmail == tmpEmail)
{ // 일정 불러온사람 기준이면(참석자가 불러온경우 일정호출자 기준이면
uEmail = tmpEmail;
uName = tmpName;
}
}
foreach (Attendee atd in fullAppt.OptionalAttendees)
{
string tmpEmail = atd.Address;
string tmpName = atd.Name;
MdCldAttendee mdAttendees = new MdCldAttendee
{
attedEmail = tmpEmail,
attedName = tmpName,
attedType = "required"
};
tmpList.attendees.Add(mdAttendees);
if (userEmail == tmpEmail)
{ // 일정 불러온사람 기준이면(참석자가 불러온경우 일정호출자 기준이면
uEmail = tmpEmail;
uName = tmpName;
}
}
tmpList.userEmail = uEmail;
tmpList.userName = uName;
tmpList.recName = string.Empty;
//tmpList.recName = GetResourceName(mEws, fullAppt, resourceNameProp, wEmail, uEmail, false); // 리스트에서 부어주기는 너무 비효율적임
rstList.Add(tmpList);
}
rstAt.success = true;
}
catch (Exception ex)
{
rstAt.message = "Ews 일정조회에 실패하였습니다.";
rstAt.exmsg = ex.Message;
ComHelper.WriteErrorLog(ex, request, bodyData, "E_R030");
}
rstAt.data = rstList;
return rstAt;
}
#endregion
#region 일정 상세정보
public MdResultT1 GetEventDetail(string userEmail, string evtID, string timeZone, HttpRequestMessage request, string bodyData)
{
GetAccessToken(userEmail);
MdCldData rstData = new MdCldData();
MdResultT1 rstAt = new MdResultT1(false, "");
if (mEws == null)
{
ComHelper.WriteErrorLog(new Exception(), request, bodyData, "E_R031");
return rstAt.SetRst(false, "Ews 권한획득에 실패하였습니다.", "", "", rstData);
}
try
{
ExtendedPropertyDefinition resourceNameProp = new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, "ResourceName", MapiPropertyType.String);
PropertySet propertySet = new PropertySet(BasePropertySet.FirstClassProperties)
{
RequestedBodyType = BodyType.Text
};
Appointment appt = Appointment.Bind(mEws, evtID, propertySet);
string wName = ComHelper.NullToEmpty(appt.Organizer?.Name);
string uName = wName;
string wEmail = ComHelper.NullToEmpty(appt.Organizer?.Address);
if (wEmail.Contains("/O=")) // X500 주소인 경우
{
// ExchangeResolveName 사용
NameResolutionCollection nameRes = mEws.ResolveName(wEmail, ResolveNameSearchLocation.DirectoryOnly, true);
if (nameRes.Count > 0)
{
wEmail = nameRes[0].Mailbox.Address;
}
}
string uEmail = wEmail;
rstData.schKey = ComHelper.NullToEmpty(appt.Id.UniqueId);
rstData.writeName = wName;
rstData.writeEmail = wEmail;
rstData.subject = ComHelper.NullToEmpty(appt.Subject);
rstData.startDate = DateTime.Parse(appt.Start.ToString("yyyy-MM-ddTHH:mm:ss"));
rstData.startZone = ComHelper.NullToEmpty(appt.Start.Kind);
rstData.endDate = DateTime.Parse(appt.End.ToString("yyyy-MM-ddTHH:mm:ss"));
rstData.endZone = ComHelper.NullToEmpty(appt.End.Kind);
rstData.location = ComHelper.NullToEmpty(appt.Location); // 장소
rstData.Importance = ComHelper.NullToEmpty(appt.Importance);
rstData.contentType = ComHelper.NullToEmpty(appt.Body.BodyType);
rstData.content = ComHelper.NullToEmpty(appt.Body.Text);
rstData.sensitivity = ComHelper.NullToEmpty(appt.Sensitivity);
rstData.repeatedYn = "N";
// 참석자 정보 추가
JArray attendees = new JArray();
foreach (Attendee atd in appt.RequiredAttendees)
{
string tmpEmail = atd.Address;
string tmpName = atd.Name;
MdCldAttendee mdAttendees = new MdCldAttendee
{
attedEmail = tmpEmail,
attedName = tmpName,
attedType = "required"
};
rstData.attendees.Add(mdAttendees);
if (userEmail == tmpEmail)
{ // 일정 불러온사람 기준이면(참석자가 불러온경우 일정호출자 기준이면
uEmail = tmpEmail;
uName = tmpName;
}
}
foreach (Attendee atd in appt.OptionalAttendees)
{
string tmpEmail = atd.Address;
string tmpName = atd.Name;
MdCldAttendee mdAttendees = new MdCldAttendee
{
attedEmail = tmpEmail,
attedName = tmpName,
attedType = "required"
};
rstData.attendees.Add(mdAttendees);
if (userEmail == tmpEmail)
{ // 일정 불러온사람 기준이면(참석자가 불러온경우 일정호출자 기준이면
uEmail = tmpEmail;
uName = tmpName;
}
}
rstData.userEmail = uEmail;
rstData.userName = uName;
rstData.recName = string.Empty;
rstData.recName = GetResourceName(mEws, appt, resourceNameProp, wEmail, uEmail, true);
rstAt.SetRst(true, "", "", "", rstData);
}
catch (Exception ex)
{
rstAt.SetRst(false, "Ews 일정조회를 실패하였습니다.", "", ex.Message, rstData);
ComHelper.WriteErrorLog(ex, request, bodyData, "E_R032");
}
return rstAt;
}
#endregion
#region 자원명 속성 찾기
///
/// 메시지를 못 찾으면 Organizer SentItems에서 읽기
///
///
/// CalendarItem ID 기반으로 ResourceName 안전하게 조회
/// Organizer/Attendee 모두 처리 가능
///
public string GetResourceName(ExchangeService service, Appointment fullAppt, ExtendedPropertyDefinition resourceNameProp, string wEmail, string uEmail, bool isAttend)
{
string resourceName = string.Empty;
try
{
if (wEmail == uEmail)
{
resourceName = GetResourceNmFromSentItems(service, fullAppt, resourceNameProp);
}
else if (isAttend)
{ // 참석자도 해당 값을 보게 할건지 여부
// 일정을 불러오는 사용자와 작성자 다른경우에는 작성자의 일정을 찾아야 하는데 키값이 다르기 때문에... 찾는 방법은 원 작성자로 접속을 해서 제목과 시작시간을 조회해서 찾아야함 (동일한게 있으면 오류가능성 있음)
ExchangeService tmpEws = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
try
{
bool isO365 = O365UserCheck(wEmail.Split('@')[0]).GetAwaiter().GetResult();
if (isO365 == false)
{
// 메일함에서 오류시 M365 사용자로 판단
string ewsUri = ConfigurationManager.AppSettings["EWSUri"];
string DomainName = ConfigurationManager.AppSettings["DomainName"];
tmpEws.UseDefaultCredentials = true;
tmpEws.PreAuthenticate = true;
tmpEws.Url = new Uri(ewsUri);
tmpEws.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, wEmail);
tmpEws.HttpHeaders.Add("X-AnchorMailbox", wEmail);
// Organizer 캘린더에서 Subject + StartTime으로 조회 (주의: 동일 일정 존재 시 첫 번째)
SearchFilter filter = new SearchFilter.SearchFilterCollection(LogicalOperator.And, new SearchFilter[]
{
new SearchFilter.IsEqualTo(AppointmentSchema.Subject, fullAppt.Subject),
new SearchFilter.IsEqualTo(AppointmentSchema.Start, fullAppt.Start),
new SearchFilter.IsEqualTo(AppointmentSchema.End, fullAppt.End)
});
ItemView view = new ItemView(5);
view.PropertySet = new PropertySet(BasePropertySet.IdOnly);
FindItemsResults- originalItems = tmpEws.FindItems(WellKnownFolderName.Calendar, filter, view);
if (originalItems.TotalCount > 0)
{
PropertySet propSet = new PropertySet(BasePropertySet.FirstClassProperties);
propSet.Add(resourceNameProp);
Appointment originalAppt = Appointment.Bind(tmpEws, originalItems.Items[0].Id, propSet);
resourceName = GetResourceNmFromSentItems(tmpEws, originalAppt, resourceNameProp);
}
}
}
catch (Exception)
{
}
}
}
catch (Exception ex)
{
ComHelper.WriteErrorLog(ex, $"writetUserEmail={wEmail}, askUserEmail={uEmail}", "GetResourceName");
}
return resourceName ?? string.Empty;
}
private string GetResourceNmFromSentItems(ExchangeService _service, Appointment appt, ExtendedPropertyDefinition resourceNameProp)
{
string resourceName = string.Empty;
try
{
if (string.IsNullOrEmpty(appt.Organizer?.Address))
return resourceName;
SearchFilter filter = new SearchFilter.IsEqualTo(EmailMessageSchema.Subject, appt.Subject);
ItemView view = new ItemView(10); // 최대 10개 조회
view.PropertySet = new PropertySet(BasePropertySet.FirstClassProperties);
view.PropertySet.Add(resourceNameProp);
FindItemsResults
- results = _service.FindItems(WellKnownFolderName.SentItems, filter, view);
foreach (EmailMessage msg in results.OfType())
{
if (msg.Sender?.Address?.Equals(appt.Organizer.Address, StringComparison.OrdinalIgnoreCase) == true)
{
if (msg.TryGetProperty(resourceNameProp, out resourceName))
{
break;
}
}
}
}
catch (Exception ex)
{
// 로그 남기기
ComHelper.WriteErrorLog(ex, "", "GetResourceNameFromSentItems");
}
return resourceName;
}
#endregion
#region 메일 발송
public MdResultBase SendMail(string userEmail, string senderEmail, List<(string Name, string Email)> toRct, List<(string Name, string Email)> ccRct, string subject, string body, string bodyType)
{
GetAccessToken(userEmail);
MdResultBase rBase = new MdResultBase(false, "", "");
List rstList = new List();
if (mEws == null)
{
ComHelper.WriteErrorLog(new Exception(), senderEmail, "E_R033");
return rBase.SetRst(false, "Ews 권한획득에 실패하였습니다.", "");
}
try
{
EmailMessage email = new EmailMessage(mEws);
email.Subject = subject;
email.Body = new MessageBody(BodyType.HTML, body);
// To 수신자 추가 (이름 + 이메일)
foreach (var recipient in toRct)
{
email.ToRecipients.Add(new EmailAddress(recipient.Name, recipient.Email));
}
foreach (var recipient in ccRct)
{
email.CcRecipients.Add(new EmailAddress(recipient.Name, recipient.Email));
}
email.Send(); // 메일발송 (보낸편지함에 저장 안함)
//email.SendAndSaveCopy(); //메일발송 후 보낸편지함에 저장
rBase.SetRst(true, "메일발송을 완료하였습니다.");
}
catch (Exception ex)
{
ComHelper.WriteErrorLog(ex, senderEmail, "E_R034");
rBase.SetRst(false, "메일발송에 실패하였습니다.", "", ex.Message);
}
return rBase;
}
public MdResultBase SendMail(string userEmail, string senderEmail, List toRct, List ccRct, string subject, string body, string bodyType)
{
GetAccessToken(userEmail);
MdResultBase rBase = new MdResultBase(false, "", "");
if (mEws == null)
{
ComHelper.WriteErrorLog(new Exception(), senderEmail, "E_R035");
return rBase.SetRst(false, "Ews 권한획득에 실패하였습니다.", "");
}
try
{
EmailMessage email = new EmailMessage(mEws);
email.Subject = subject;
email.Body = new MessageBody(BodyType.HTML, body);
// To 수신자 추가 (이름 + 이메일)
foreach (MdRscAttendee recipient in toRct)
{
email.ToRecipients.Add(new EmailAddress(recipient.userNm, recipient.mail));
}
foreach (MdRscAttendee recipient in ccRct)
{
email.CcRecipients.Add(new EmailAddress(recipient.userNm, recipient.mail));
}
email.Send(); // 메일발송 (보낸편지함에 저장 안함)
//email.SendAndSaveCopy(); //메일발송 후 보낸편지함에 저장
rBase.SetRst(true, "메일발송을 완료하였습니다.");
}
catch (Exception ex)
{
ComHelper.WriteErrorLog(ex, senderEmail, "E_R036");
rBase.SetRst(false, "메일발송에 실패하였습니다.", "", ex.Message);
}
return rBase;
}
#endregion
}
}
------------------------------------------------------------------------------------------------
using Microsoft.Exchange.WebServices.Data;
using Microsoft.Identity.Client;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RestApi.Models;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http.Results;
namespace RestApi.Services
{
public class GraphHelper
{
private string _GraphTenantID;
private string _GraphClientID;
private string _GraphClientSecret;
private string _GraphAuthority;
private string[] _GraphScope;
private string _Endpoint;
private string _AccessToken;
#region 생성자 기초데이터터 획득
public GraphHelper()
{
_GraphTenantID = ConfigurationManager.AppSettings["GraphTenantID"];
_GraphClientID = ConfigurationManager.AppSettings["GraphClientID"];
_GraphClientSecret = ConfigurationManager.AppSettings["GraphClientSecret"];
_GraphAuthority = $"https://login.microsoftonline.com/{_GraphTenantID}";
_GraphScope = new[] { ConfigurationManager.AppSettings["GraphScope"] };
//_GraphGrantType = ConfigurationManager.AppSettings["GraphGrantType"];
}
#endregion
#region Graph 권한 획득
public async Task GetAccessTokenAsync(string userEmail)
{
if (string.IsNullOrWhiteSpace(_AccessToken))
{
try
{
_Endpoint = $"https://graph.microsoft.com/v1.0/users/{userEmail}/events";
var app = ConfidentialClientApplicationBuilder.Create(_GraphClientID).WithClientSecret(_GraphClientSecret).WithAuthority(new Uri(_GraphAuthority)).Build();
var result = await app.AcquireTokenForClient(_GraphScope).ExecuteAsync();
_AccessToken = result.AccessToken;
}
catch (Exception ex)
{
ComHelper.WriteErrorLog(ex, userEmail, "E_R041");
}
}
return _AccessToken;
}
#endregion
#region 일정 등록
public async Task> CreateEventAsync(string userEmail, string subject, string cttsType, string ctts, DateTime startDate, DateTime endDate, string timeZone
, string location, string recName, int reminderMinutes, string sensitivity, string importance, JArray attendees, bool isDetail, HttpRequestMessage request, string bodyData, string tmpLog)
{
await GetAccessTokenAsync(userEmail);
MdResultT1 rstAt = new MdResultT1(false, "");
string scheduleID = "";
if (string.IsNullOrWhiteSpace(_AccessToken))
{
rstAt.message = "M365 권한획득에 실패하였습니다.";
ComHelper.WriteErrorLog(rstAt.message, request, bodyData, "E_R042");
return rstAt;
}
string tmpPoint = _Endpoint;
try
{
JObject newEvent = new JObject();
newEvent["subject"] = subject;
newEvent["body"] = new JObject { ["contentType"] = cttsType, ["content"] = ctts };
newEvent["start"] = new JObject { ["dateTime"] = startDate.ToString("yyyy-MM-ddTHH:mm:ss"), ["timeZone"] = timeZone };
newEvent["end"] = new JObject { ["dateTime"] = endDate.ToString("yyyy-MM-ddTHH:mm:ss"), ["timeZone"] = timeZone };
newEvent["importance"] = importance; // 중요도 설정
newEvent["sensitivity"] = sensitivity; // 민감도 설정
newEvent["reminderMinutesBeforeStart"] = reminderMinutes; // 몇분전 전에 알림
newEvent["isAllDay"] = false; // 하루 종일 일정이 아님
//newEvent["categories"] = new JArray { "Red category" }; // Outlook에서 설정한 카테고리 이름
//newEvent["showAs"] = "busy"; // 바쁨 상태로 표시
newEvent["location"] = new JObject { ["displayName"] = location };
/* 속성 저장
newEvent["singleValueExtendedProperties"] = new JArray
{
new JObject
{
["id"] = "String {00020329-0000-0000-C000-000000000046} Name ResourceName",
["value"] = recName
}
};
*/
if (attendees != null && attendees.Count > 0)
{
try
{
JArray formattedAttendees = new JArray();
foreach (JObject itm in attendees)
{
string name = itm["attedName"].ToString();
string email = itm["attedEmail"].ToString();
string type = itm["attedType"].ToString();
JObject formattedAttendee = new JObject
{
["emailAddress"] = new JObject
{
["address"] = email,
["name"] = name
},
["type"] = type.ToLower()
};
formattedAttendees.Add(formattedAttendee);
}
newEvent["attendees"] = formattedAttendees;
}
catch (Exception ex1)
{
ComHelper.WriteErrorLog(ex1, request, bodyData, "E_R043");
rstAt.message = "참석자 정보 필수값이 없습니다. 확인하여 주세요.[M365]";
return rstAt;
}
}
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _AccessToken);
var sendJson = JsonConvert.SerializeObject(newEvent, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var content = new StringContent(newEvent.ToString(), Encoding.UTF8, "application/json");
var response = await client.PostAsync(tmpPoint, content);
string result = await response.Content.ReadAsStringAsync();
rstAt.success = response.IsSuccessStatusCode;
if (response.IsSuccessStatusCode)
{
// JSON 파싱
var jsonResult = JObject.Parse(result);
if (string.IsNullOrWhiteSpace(jsonResult["id"].ToString()) == false)
{
scheduleID = jsonResult["id"].ToString();// 이벤트 ID 가져오기
rstAt.key = scheduleID;
if (isDetail)
{
MdResultT1 tmpAt = await GetEventDetailAsync(userEmail, rstAt.key, timeZone, request, bodyData);
rstAt.data = tmpAt.data;
}
}
}
else
{
rstAt.message = "M365 일정등록에 실패하였습니다.";
rstAt.exmsg = result;
ComHelper.WriteErrorLog(result, request, bodyData, "E_R044");
}
}
}
catch (Exception ex2)
{
rstAt.message = "M365 일정등록에 실패하였습니다.";
rstAt.exmsg = ex2.Message;
ComHelper.WriteErrorLog(ex2, request, bodyData, "E_R045");
}
finally
{
string strLog = $"userEmail:{userEmail}{Environment.NewLine}subject:{subject}{Environment.NewLine}cttsType:{cttsType}{Environment.NewLine}location:{location}{Environment.NewLine}{tmpLog}{Environment.NewLine}scheduleID : {scheduleID}";
ComHelper.WriteTextLog(request, bodyData, strLog, "");
}
return rstAt;
}
#endregion
#region 일정 수정
public async Task> UpdateEventAsync(string userEmail, string evtID, string subject, string cttsType, string ctts, DateTime startDate, DateTime endDate, string timeZone
, string location, string recName, int reminderMinutes, string sensitivity, string importance, JArray attendees, bool isDetail, HttpRequestMessage request, string bodyData, string tmpLog)
{
string strLog = $"evtID:{evtID}{Environment.NewLine}userEmail:{userEmail}{Environment.NewLine}subject:{subject}{Environment.NewLine}cttsType:{cttsType}{Environment.NewLine}location:{location}{Environment.NewLine}" + tmpLog;
ComHelper.WriteTextLog(request, bodyData, strLog, "");
await GetAccessTokenAsync(userEmail);
string tmpPoint = $"{_Endpoint}/{evtID}";
MdResultT1 rstAt = new MdResultT1(false, "");
if (string.IsNullOrWhiteSpace(_AccessToken))
{
rstAt.message = "M365 권한획득에 실패하였습니다.";
ComHelper.WriteErrorLog(rstAt.message, request, bodyData, "E_R046");
return rstAt;
}
try
{
JObject newEvent = new JObject();
newEvent["subject"] = subject;
newEvent["body"] = new JObject { ["contentType"] = cttsType, ["content"] = ctts };
newEvent["start"] = new JObject { ["dateTime"] = startDate.ToString("yyyy-MM-ddTHH:mm:ss"), ["timeZone"] = timeZone };
newEvent["end"] = new JObject { ["dateTime"] = endDate.ToString("yyyy-MM-ddTHH:mm:ss"), ["timeZone"] = timeZone };
newEvent["importance"] = importance; // 중요도 설정
newEvent["sensitivity"] = sensitivity; // 민감도 설정
newEvent["reminderMinutesBeforeStart"] = reminderMinutes; // 몇분전 전에 알림
newEvent["isAllDay"] = false; // 하루 종일 일정이 아님
//newEvent["categories"] = new JArray { "Red category" }; // Outlook에서 설정한 카테고리 이름
//newEvent["showAs"] = "busy"; // 바쁨 상태로 표시
newEvent["location"] = new JObject { ["displayName"] = location };
/* 속성 저장
newEvent["singleValueExtendedProperties"] = new JArray
{
new JObject
{
["id"] = "String {00020329-0000-0000-C000-000000000046} Name ResourceName",
["value"] = recName
}
};
*/
if (attendees != null && attendees.Count == 0)
{
newEvent["attendees"] = new JArray();
}
else
{
try
{
JArray formattedAttendees = new JArray();
foreach (JObject itm in attendees)
{
string name = itm["attedName"].ToString();
string email = itm["attedEmail"].ToString();
string type = itm["attedType"].ToString();
JObject formattedAttendee = new JObject
{
["emailAddress"] = new JObject
{
["address"] = email,
["name"] = name
},
["type"] = type.ToLower()
};
formattedAttendees.Add(formattedAttendee);
}
newEvent["attendees"] = formattedAttendees;
}
catch (Exception ex1)
{
ComHelper.WriteErrorLog(ex1, request, bodyData, "E_R047");
rstAt.message = "참석자 정보 필수값이 없습니다. 확인하여 주세요.[M365]";
return rstAt;
}
}
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _AccessToken);
var sendJson = JsonConvert.SerializeObject(newEvent, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
var content = new StringContent(sendJson, Encoding.UTF8, "application/json");
var rquest = new HttpRequestMessage(new HttpMethod("PATCH"), tmpPoint) { Content = content };
var response = await client.SendAsync(rquest);
string result = await response.Content.ReadAsStringAsync();
rstAt.success = response.IsSuccessStatusCode;
if (response.IsSuccessStatusCode)
{
// JSON 파싱
var jsonResult = JObject.Parse(result);
rstAt.key = jsonResult["id"].ToString();// 이벤트 ID 가져오기
if (isDetail)
{
MdResultT1 tmpAt = await GetEventDetailAsync(userEmail, rstAt.key, timeZone, request, bodyData);
rstAt.data = tmpAt.data;
}
}
else
{
rstAt.message = "M365 일정수정에 실패하였습니다.";
rstAt.exmsg = result;
ComHelper.WriteErrorLog(result, request, bodyData, "E_R048");
}
}
}
catch (Exception ex2)
{
rstAt.message = "M365 일정수정에 실패하였습니다.";
rstAt.exmsg = ex2.Message;
ComHelper.WriteErrorLog(ex2, request, bodyData, "E_R049");
}
return rstAt;
}
#endregion
#region 일정 삭제
public async Task DeleteEventAsync(string userEmail, string evtID, HttpRequestMessage request, string bodyData, string tmpLog)
{
ComHelper.WriteTextLog(request, bodyData, $"userEmail:{userEmail}, {tmpLog}", evtID);
MdResultBase rBase = new MdResultBase(false, "");
await GetAccessTokenAsync(userEmail);
if (string.IsNullOrWhiteSpace(_AccessToken))
{
rBase.SetRst(false, "M365 권한획득에 실패하였습니다.", "G02");
ComHelper.WriteErrorLog("M365 권한획득에 실패하였습니다", request, bodyData, "E_R050");
return rBase;
}
string tmpPoint = $"{_Endpoint}/{Uri.EscapeDataString(evtID)}";
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _AccessToken);
var response = await client.DeleteAsync(tmpPoint);
if (response.IsSuccessStatusCode)
{
rBase.SetRst(true, "일정 삭제가 완료 되었습니다.", "SSS");
}
else
{
string result = await response.Content.ReadAsStringAsync();
rBase.SetRst(false, "M365 일정삭제에 실패하였습니다.", "G03", result);
ComHelper.WriteErrorLog(result, request, bodyData, "E_R051");
}
}
}
catch (Exception ex)
{
rBase.SetRst(false, "M365 일정삭제에 실패하였습니다.", "G00", ex.Message);
ComHelper.WriteErrorLog(ex, request, bodyData, "E_R052");
}
return rBase;
}
#endregion
#region 일정 리스트
public async Task>> GetEventListAsync(string userEmail, DateTime startDate, DateTime endDate, string timeZone, HttpRequestMessage request, string bodyData)
{
await GetAccessTokenAsync(userEmail);
TimeZoneInfo kst = TimeZoneInfo.FindSystemTimeZoneById("Korea Standard Time");
DateTime utcSTime = TimeZoneInfo.ConvertTimeToUtc(startDate, kst);
DateTime utcETime = TimeZoneInfo.ConvertTimeToUtc(endDate, kst);
MdResultT1
> rstAt = new MdResultT1>(false, "", "", "", new List());
if (string.IsNullOrWhiteSpace(_AccessToken))
{
rstAt.message = "M365 권한획득에 실패하였습니다.";
ComHelper.WriteErrorLog(rstAt.message, request, bodyData, "E_R053");
return rstAt;
}
// calendarView 사용: 기간 지정
string tmpPoint = $"https://graph.microsoft.com/v1.0/users/{userEmail}/calendarView?startDateTime={utcSTime.ToString("o")}&endDateTime={utcETime.ToString("o")}&$top=1000";
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _AccessToken);
client.DefaultRequestHeaders.Add("Prefer", $"outlook.timezone=\"{timeZone}\"");
var response = await client.GetAsync(tmpPoint);
string result = await response.Content.ReadAsStringAsync();
rstAt.success = response.IsSuccessStatusCode;
if (response.IsSuccessStatusCode)
{
JObject json = JObject.Parse(result);
JArray events = (JArray)json["value"];
foreach (var item in events)
{
//취소된 일정인 경우 생략
if (bool.Parse(item["isCancelled"].ToString()) == false)
{
string appName = ComHelper.NullToEmpty(item["organizer"]?["emailAddress"]?["name"]);
string appEmail = ComHelper.NullToEmpty(item["organizer"]?["emailAddress"]?["address"]);
MdCldData tmpList = new MdCldData();
tmpList.schKey = ComHelper.NullToEmpty(item["id"]);
tmpList.userName = appName;
tmpList.writeName = appName;
tmpList.userEmail = appEmail;
tmpList.writeEmail = appEmail;
tmpList.subject = ComHelper.NullToEmpty(item["subject"]);
tmpList.startDate = DateTime.Parse(item["start"]?["dateTime"]?.ToString());
tmpList.startZone = ComHelper.NullToEmpty(item["start"]?["timeZone"]?.ToString());
tmpList.endDate = DateTime.Parse(item["end"]?["dateTime"]?.ToString());
tmpList.endZone = ComHelper.NullToEmpty(item["end"]?["timeZone"]?.ToString());
tmpList.location = ComHelper.NullToEmpty(item["location"]?["displayName"]?.ToString()); // 장소
tmpList.Importance = ComHelper.NullToEmpty(item["importance"]);
tmpList.contentType = ComHelper.NullToEmpty(item["body"]?["contentType"]?.ToString());
tmpList.content = ComHelper.NullToEmpty(item["body"]?["content"]?.ToString());
tmpList.sensitivity = ComHelper.NullToEmpty(item["sensitivity"]?.ToString());
tmpList.repeatedYn = "N";
string resourceName = string.Empty;
/* 속성 불러오기
var extProps = item["singleValueExtendedProperties"] as JArray;
if (extProps != null && extProps.Count > 0)
{
resourceName = ComHelper.NullToEmpty(extProps[0]?["value"]?.ToString());
}
*/
tmpList.recName = resourceName;
var attendeesArray = item["attendees"] as JArray;
if (attendeesArray != null)
{
foreach (var attendee in attendeesArray)
{
string tmpEmail = ComHelper.NullToEmpty(attendee["emailAddress"]?["address"]?.ToString());
string tmpName = ComHelper.NullToEmpty(attendee["emailAddress"]?["name"]?.ToString());
MdCldAttendee mdAttendees = new MdCldAttendee
{
attedEmail = tmpEmail,
attedName = tmpName,
attedType = ComHelper.NullToEmpty(attendee["type"])
};
tmpList.attendees.Add(mdAttendees);
if (userEmail == tmpEmail)
{ // 일정 불러온사람 기준이면(참석자가 불러온경우 일정호출자 기준이면
tmpList.userEmail = tmpEmail;
tmpList.userName = tmpName;
}
}
}
rstAt.data.Add(tmpList);
}
}
}
else
{
rstAt.message = "M365 데이터를 가져오는데 실패하였습니다.";
ComHelper.WriteErrorLog(rstAt.message, request, bodyData, "E_R054");
}
}
}
catch (Exception ex)
{
rstAt.message = "M365 일정조회에 실패하였습니다.";
rstAt.exmsg = ex.Message;
ComHelper.WriteErrorLog(ex, request, bodyData, "E_R055");
}
return rstAt;
}
#endregion
#region 일정 상세정보
public async Task> GetEventDetailAsync(string userEmail, string evtID, string timeZone, HttpRequestMessage request, string bodyData)
{
await GetAccessTokenAsync(userEmail);
MdResultT1 rstAt = new MdResultT1(false, "");
if (string.IsNullOrWhiteSpace(_AccessToken))
{
rstAt.message = "M365 권한획득에 실패하였습니다.";
ComHelper.WriteErrorLog(rstAt.message, request, bodyData, "E_R056");
return rstAt;
}
string tmpPoint = $"https://graph.microsoft.com/v1.0/users/{userEmail}/events/{Uri.EscapeDataString(evtID)}" + " ?$select=id,subject,body,attendees,organizer,start,end,location,importance,sensitivity";
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _AccessToken);
client.DefaultRequestHeaders.Add("Prefer", $"outlook.timezone=\"{timeZone}\"");
var response = await client.GetAsync(tmpPoint);
string result = await response.Content.ReadAsStringAsync();
MdCldData rstData = new MdCldData();
if (response.IsSuccessStatusCode)
{
JObject item = JObject.Parse(result);
string appName = ComHelper.NullToEmpty(item["organizer"]?["emailAddress"]?["name"]);
string appEmail = ComHelper.NullToEmpty(item["organizer"]?["emailAddress"]?["address"]);
rstData.schKey = ComHelper.NullToEmpty(item["id"]);
rstData.userName = appName;
rstData.writeName = appName;
rstData.userEmail = appEmail;
rstData.writeEmail = appEmail;
rstData.subject = ComHelper.NullToEmpty(item["subject"]);
rstData.startDate = DateTime.Parse(item["start"]?["dateTime"]?.ToString());
rstData.startZone = ComHelper.NullToEmpty(item["start"]?["timeZone"]?.ToString());
rstData.endDate = DateTime.Parse(item["end"]?["dateTime"]?.ToString());
rstData.endZone = ComHelper.NullToEmpty(item["end"]?["timeZone"]?.ToString());
rstData.location = ComHelper.NullToEmpty(item["location"]?["displayName"]?.ToString()); // 장소
rstData.Importance = ComHelper.NullToEmpty(item["importance"]);
rstData.contentType = ComHelper.NullToEmpty(item["body"]?["contentType"]?.ToString());
rstData.content = ComHelper.NullToEmpty(item["body"]?["content"]?.ToString());
rstData.sensitivity = ComHelper.NullToEmpty(item["sensitivity"]?.ToString());
rstData.repeatedYn = "N";
string resourceName = string.Empty;
/* 속성 불러오기
var extProps = item["singleValueExtendedProperties"] as JArray;
if (extProps != null && extProps.Count > 0)
{
resourceName = ComHelper.NullToEmpty(extProps[0]?["value"]?.ToString());
}
*/
rstData.recName = resourceName;
var attendeesArray = item["attendees"] as JArray;
if (attendeesArray != null)
{
foreach (var attendee in attendeesArray)
{
string tmpEmail = ComHelper.NullToEmpty(attendee["emailAddress"]?["address"]?.ToString());
string tmpName = ComHelper.NullToEmpty(attendee["emailAddress"]?["name"]?.ToString());
MdCldAttendee mdAttendees = new MdCldAttendee
{
attedEmail = tmpEmail,
attedName = tmpName,
attedType = ComHelper.NullToEmpty(attendee["type"])
};
rstData.attendees.Add(mdAttendees);
if (userEmail == tmpEmail)
{
rstData.userName = tmpName;
rstData.userEmail = tmpEmail;
}
}
}
}
rstAt.success = response.IsSuccessStatusCode;
rstAt.data = rstData;
}
}
catch (Exception ex)
{
rstAt.message = "M365 일정조회에 실패하였습니다.";;
rstAt.exmsg = ex.Message;
ComHelper.WriteErrorLog(ex, request, bodyData, "E_R057");
}
return rstAt;
}
#endregion
#region 메일 발송
public async Task SendMailAsync(string userEmail, string senderEmail, List<(string Name, string Email)> toRct, List<(string Name, string Email)> ccRct, string subject, string body, string bodyType)
{
MdResultBase rBase = new MdResultBase(false, "");
await GetAccessTokenAsync(userEmail);
if (string.IsNullOrWhiteSpace(_AccessToken))
{
rBase.SetRst(false, "M365 권한획득에 실패하였습니다.");
ComHelper.WriteErrorLog(new Exception(), senderEmail, "E_R058");
return rBase;
}
string sUrl = $"https://graph.microsoft.com/v1.0/users/{userEmail}/sendMail";
try
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _AccessToken);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//List<(string address, string name)> toList = new List<(string address, string name)>();
var message = new
{
message = new
{
subject = subject,
body = new
{
contentType = bodyType,
content = body
},
toRecipients = toRct,
ccRecipients = ccRct
},
saveToSentItems = false
};
var json = JsonConvert.SerializeObject(message);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(sUrl, content);
if (response.IsSuccessStatusCode)
{
rBase.SetRst(true, "M365 메일발송완료.");
}
else
{
var error = await response.Content.ReadAsStringAsync();
ComHelper.WriteErrorLog(new Exception(), senderEmail, "E_R059");
}
}
}
catch (Exception ex)
{
rBase.SetRst(false, "M365 메일발송에 실패하였습니다.", "", ex.Message);
ComHelper.WriteErrorLog(ex, senderEmail, "E_R060");
}
return rBase;
}
public async Task SendMailAsync(string userEmail, string senderEmail, List toRct, List ccRct, string subject, string body, string bodyType)
{
MdResultBase rBase = new MdResultBase(false, "");
await GetAccessTokenAsync(userEmail);
if (string.IsNullOrWhiteSpace(_AccessToken))
{
rBase.SetRst(false, "M365 권한획득에 실패하였습니다.");
ComHelper.WriteErrorLog(new Exception(), senderEmail, "E_R061");
return rBase;
}
string sUrl = $"https://graph.microsoft.com/v1.0/users/{userEmail}/sendMail";
try
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _AccessToken);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//List<(string address, string name)> toList = new List<(string address, string name)>();
// 받는 사람(To)
var toList = toRct.Select(r => new { emailAddress = new{ address = r.mail, name = r.userNm} }).ToList();
var ccList = ccRct.Select(r => new { emailAddress = new { address = r.mail, name = r.userNm } }).ToList();
var message = new
{
message = new
{
subject = subject,
body = new
{
contentType = bodyType,
content = body
},
toRecipients = toList,
ccRecipients = ccList
},
saveToSentItems = false
};
var json = JsonConvert.SerializeObject(message);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(sUrl, content);
if (response.IsSuccessStatusCode)
{
rBase.SetRst(true, "M365 메일발송완료.");
}
else
{
var error = await response.Content.ReadAsStringAsync();
ComHelper.WriteErrorLog(new Exception(error), senderEmail, "E_R062");
rBase.SetRst(false, "M365 메일발송에 실패하였습니다.", "", error);
}
}
}
catch (Exception ex)
{
rBase.SetRst(false, "M365 메일발송에 실패하였습니다.", "", ex.Message);
ComHelper.WriteErrorLog(ex, senderEmail, "E_R063");
}
return rBase;
}
#endregion
}
}
댓글 없음:
댓글 쓰기