티스토리 뷰
======================================================
안녕하세요 Doridori 입니다.
간만에 본사를 와서 그런지 조직이 변경 되어서 그런지 해야 하는 일이 많아서 정신 없었는데,
그 와중에 코로나 까지 걸려 버렸습니다. (결국... ㅜㅠ)
다행히 잘 지나가기는 하였으나 거의 10일 정도를 고생 한듯 하고, (백신 맞을 때 부터 조짐이 이상하긴 했습니다. ㅋㅋ)
2주가 지났는데도 기침이 멈추지를 않고 있기는 합니다.
다행히 조금씩 나아지기는 하네요.
이미 조심한다고 쉽게 넘어갈 수 있는 상황은 아니긴 한것 같지만 조심 하시고 무탈 하시기를 기원 합니다.
뭔가 만드는 시간에 비해 구독해주시는 분이 정체에 접어 든것 같아서 고민 중인데, 주변 지인 들이 계속 영상에 썸네일 넣으라고 많이들 하시는데 영상 개수가 많아 지다보니 고민이 많이 되네요 ㅎㅎ
항상 그렇지만 이런 저런 고민들을 많이 하고 있는 시기입니다.
모두 화이팅 하십시오!!
======================================================
62. 메일 보내기 (send email)
UI) (이전 강의 전체 Source를 받아서 시작하시면 됩니다.)
DB) (Access DB를 별도로 첨부 했습니다. (전체 Source에 포함되어 있습니다.))
Soruce) (소스에 있는 계정 정보는 삭제 하였습니다.)
교재)
지난번 강의에 메일을 전송 하는 내용을 만들어 봤는데 그냥 메일을 보내면 심심하기도 하고 실제 어떤 식으로 사용 하는지 편린이라도 보면 좋을 듯 하여 간단한 샘플을 하나 만들어 봤습니다.
뭐든 배워 놓으면 기본을 배우기 때문에 그냥 사용하는 경우는 거의 없기는 한데 이런식으로도 쓰면 뭔가 더 장점이 있겠구나 정도를 생각 해 보는것도 좋지 않을까 싶어서 만들어 봤습니다.
만들다 보니 소스코드를 따라 작성 하는 것보다 프로그램 구성을 파악하는게 훨씬 더 도움이 되지 않을까 싶어서 최대한 프로그램이 돌아가는 모습이 한눈에 보이도록 그림그리려고 고민을 정말 많이 한듯 합니다.
(3번 정도를 새로 그렸습니다. ㅋㅋ)
화면은 지난번 화면을 살짝 고치고 프로그램 소스에서 동작하는 구간들이 많기 때문에 화면에 표시해서 동작하는 모습이 조금이나마 눈에 보이도록 구성 하였습니다.
기존에 작성 했던 DB 예제를 최대한 그대로 끼워 넣어서 만든 코드이기 때문에 쿼리 작성 하는 부분들도 다 Main에 넣어 놓았으니 디자인 패턴 같은거 가지고 말씀 하시면 나중에 따로 하겠습니다. :)
강의)
위에서도 말씀 드렸지만 아직 목상태가 좋지는 않아서 목이 잠기는 경우가 많기는 한데 제 성격상 하고 있는 걸 마무리를 하지 않으면 다음 내용에 대해 집중을 못하기 때문에 살짝 무리해서 만들었습니다.
내용은 괜찮으니 재미있게 봐주시면 감사 드리겠습니다.
Source)
나머지 부분은 기존과 거의 동일 하니 Main과 DB 부분만 추가하도록 하겠습니다.
(나머지 부분은 이전 강의 올려놓은 부분을 참고해도 충분 할듯 합니다.)
Form1)
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
247
248
249
250
251
252
253
|
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace emailTest
{
public partial class Form1 : Form
{
#region 전역변수
/// <summary>
/// Table Column 값 Enum
/// </summary>
enum enCol
{
ID,
작성일시,
받는이,
참조,
숨김,
제목,
내용,
전송여부,
전송일시,
전송결과,
미전송사유,
}
string _strProgramPath = Application.StartupPath + @"\EMailSendInfo.mdb"; // 프로그램 실행 경로 + DB명 (Open File Dalog로 진행해도 좋을 듯)
cDBConnect _db; // DB 연결용 Class 사용
cEMail eMail; // Mail 전송용 Class 사용 ?? 이거 어따쓰는거지? Mail 전송 시 호출 할려고 한거 같은데 전송 하는게 어디 간거지?
#endregion
public Form1()
{
InitializeComponent();
}
#region Form Event
/// <summary>
/// Form Load Event
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Form1_Load(object sender, EventArgs e)
{
_db = new cDBConnect(_strProgramPath); // Form Load 시 DB 연결
// UserControl 명칭 등록
ucARsend.StrTitle = "받는이";
ucARreg.StrTitle = "참조";
ucARhide.StrTitle = "숨김";
// EMail 전송 주소 등록
eMail = new cEMail("본인 EMail 주소", "닉네임"); // EMail 주소, Nic 입력
fTimerStart(); // Form Loading 시 Timmer 시작 (DB를 조회 하여 최신 Data가 등록 될 경우 가져와서 내부 Queue에 쌓아 놓음)
}
/// <summary>
/// Mail Send (DB 저장) Button Click 시 Event
/// > 이전 강의에서는 Mail Send 기능이었으나 DB에 저장하는 형태로 변경
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSendMail_Click(object sender, EventArgs e)
{
DateTime dt = DateTime.Now; // 현재 시간을 가져옴
// DB에서 Mail 주소등록 하는 형이 문자형으로 배열을 문자로 연결
string strARsend = string.Join(",", ucARsend.LAddress); // 42강 List 조금 더 알기 강의 참조
string strARreg = string.Join(",", ucARreg.LAddress);
string strARhide = string.Join(",", ucARhide.LAddress);
// 저장 전 Data Null Check
if (String.IsNullOrEmpty(strARsend) /*|| String.IsNullOrEmpty(strARreg) || String.IsNullOrEmpty(strARhide)*/ // 참고와 숨김 부분은 필수 입력은 아님
|| String.IsNullOrEmpty(tboxSubject.Text) || String.IsNullOrEmpty(tboxBody.Text))
{
MessageBox.Show("[Subject, Body, 받은이]는 필수 입력 값 입니다.");
return;
}
// Insert Query (잘 사용 하지않는 Access DB Query로 그렇게 중요하지는 않을 듯 (가능 하면 SQL이나 Oracle DB로 연결하여 Query를 보는게 도움이 될듯)
string Query = $@"INSERT INTO TB_MAIL_INFO
({enCol.작성일시}, {enCol.받는이}, {enCol.참조}, {enCol.숨김}, {enCol.제목}, {enCol.내용}, {enCol.전송여부})
VALUES (""{dt}"", ""{strARsend}"", ""{strARreg}"", ""{strARhide}"", ""{tboxSubject.Text}"", ""{tboxBody.Text}"", ""N"")";
DataSet ds = _db.QueryExeCute(Query);
fSelectEMailInfo(); // Data 저장 후 화면 Update
}
// 조회만을 위해 사용 하고 있으나 삭제 예정 필요 없을 듯 한데???
private void button1_Click(object sender, EventArgs e)
{
fSelectEMailInfo();
}
#endregion
#region Inner Function
/// <summary>
/// DB Data 조회 (Data 변화 확인 용도)
/// </summary>
private void fSelectEMailInfo()
{
// Select Query
string Query = $@"SELECT *
FROM TB_MAIL_INFO
ORDER BY ID DESC";
DataSet ds = _db.QueryExeCute(Query);
dgEMailInfo.DataSource = ds.Tables[0];
}
#endregion
#region Timer Queue Function
Timer _tmDBSelect = new Timer(); // DB에서 최신 Data가 있는지 Check 하는 Timer
Timer _tmQueueMailing = new Timer(); // Queue에 있는 Data를 Mailing 하는 Timer
Queue<DataRow> _QMailData = new Queue<DataRow>(); // Mail 전송 정보를 저장해 놓을 Queue
private void fTimerStart()
{
// DB Data Check 용 Timer
_tmDBSelect.Interval = 3000; // 3초 기준 1회 동작
_tmDBSelect.Tick += _tmDBSelect_Tick;
_tmDBSelect.Start();
// Queue Data Mailing 용 Timer
_tmQueueMailing.Interval = 5000; // 3초 기준 1회 동작
_tmQueueMailing.Tick += _tmQueueMailing_Tick;
_tmQueueMailing.Start();
}
/// <summary>
/// Queue에 있는 Data를 하나씩 빼서 Mail 전송
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void _tmQueueMailing_Tick(object sender, EventArgs e)
{
int iCount = _QMailData.Count;
lblQueueCount.Text = iCount.ToString();
if (iCount <= 0) return; // Queue에 들어 있는 정보가 없을 경우 return;
string strRet = string.Empty;
// 1. Queue에 있는 Data를 하나 씩 빼냄
DataRow oRow = _QMailData.Dequeue();
int iID = (int)oRow[enCol.ID.ToString()];
lboxQData.Items.Remove(iID); // Queue 정보를 List box에 보여주기 위해서 Update
// 2. Mail 전송 Data로 변환 후 Mail 전송
string strSubject = oRow[enCol.제목.ToString()].ToString();
string strBody = oRow[enCol.내용.ToString()].ToString();
List<string> toSend = oRow[enCol.받는이.ToString()].ToString().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList<string>(); // Split 했을 때 배열에 넣을 값이 없을 경우 Empty 값을 넣지 않기 위해 Split Option 사용
List<string> toReg = oRow[enCol.참조.ToString()].ToString().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList<string>();
List<string> toHide = oRow[enCol.숨김.ToString()].ToString().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList<string>();
strRet = eMail.SendEMail(strSubject, strBody, toSend, toReg, toHide); // Mail Send 이후 결과 반환
string strSendResult = (String.IsNullOrEmpty(strRet)) ? "Y" : "N";
fDataReadUpdate(iID, strSendResult, strRet); // Mailing 결과 Update
// Mail Send 후 Return을 보기 위해서 재조회
fSelectEMailInfo();
}
/// <summary>
/// DB에서 읽어 오지 않은 최신 Data가 있는지 확인하고 Queue에 저장 한 뒤 Data Update
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void _tmDBSelect_Tick(object sender, EventArgs e)
{
// 1. 전송 하지 않은 Mail 정보를 Loading
string Query = $@"SELECT *
FROM TB_MAIL_INFO
WHERE 전송여부 = ""N""
ORDER BY 작성일시";
DataSet ds = _db.QueryExeCute(Query);
// 하나씩 Queue에 담아 놓고 Update
foreach (DataRow oRow in ds.Tables[0].Rows)
{
int iID = (int)oRow[enCol.ID.ToString()];
_QMailData.Enqueue(oRow);
lboxQData.Items.Add(iID);
fDataReadUpdate(iID);
}
lblQueueCount.Text = _QMailData.Count.ToString();
// 결과 항목이 있을 경우에만 DB 재조회 진행
if (ds.Tables[0].Rows.Count > 0)
{
fSelectEMailInfo();
}
}
/// <summary>
/// Update Query 호출 (DB Select 이후 전송 여부 업데이트)
/// </summary>
private void fDataReadUpdate(int iNo)
{
DateTime dt = DateTime.Now; // 현재 시간을 가져옴
string Query = $@"UPDATE TB_MAIL_INFO SET 전송여부 = ""Y"", 전송일시 = ""{dt}"" WHERE ID = {iNo}";
DataSet ds = _db.QueryExeCute(Query);
}
/// <summary>
/// Update Query 호출 (Mailing 전송 이후 결과 업데이트)
/// </summary>
/// <param name="iNo"></param>
private void fDataReadUpdate(int iNo, string strSendResult, string strErrorMessage)
{
DateTime dt = DateTime.Now; // 현재 시간을 가져옴
string Query = $@"UPDATE TB_MAIL_INFO SET 전송결과 = ""{strSendResult}"", 미전송사유 = ""{strErrorMessage}"", 전송일시 = ""{dt}"" WHERE ID = {iNo}";
DataSet ds = _db.QueryExeCute(Query);
}
#endregion
}
}
|
cs |
cDBConnect)
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
|
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace emailTest
{
class cDBConnect
{
System.Data.OleDb.OleDbConnection _conn;
public cDBConnect(string strDBPath)
{
// DataAdapter는 자동으로 Connection을
// 핸들링한다. conn.Open() 불필요.
string connStr = $@"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={strDBPath}";
_conn = new OleDbConnection(connStr);
/*
string Query = $@"SELECT *
FROM Voca";
QueryExeCute(Query);
*/
}
public DataSet QueryExeCute(string Query)
{
// Fill 전달 전에 DataSet객체 생성
DataSet ds = new DataSet();
System.Data.OleDb.OleDbDataAdapter adp = new OleDbDataAdapter(Query, _conn);
adp.Fill(ds);
return ds;
}
public bool UpdateQuery()
{
return true;
}
}
}
|
cs |
'C# > C# 강좌 Winform' 카테고리의 다른 글
Doridori C# 강의 3) 65. Logging (log4net) (0) | 2022.11.24 |
---|---|
Doridori C# 강의 3) 64. 광학문자인식 (Screenshot & OCR) (0) | 2022.10.22 |
Doridori C# 강의 3) 62. 메일 보내기 (send email) (17) | 2022.06.19 |
Doridori C# 강의 3) 61. 정규식 (Regular Expression) (4) | 2022.05.06 |
Doridori C# 강의 3) 60. 분산처리 프로그램 (Parallel) (2) | 2022.03.08 |
- Total
- Today
- Yesterday
- 칵테일
- 맥주
- 주말
- C# 강좌
- 광저우
- 소주
- 가볼만한곳
- 위스키
- 와인
- 서울
- 모바일
- 프로그램 강의
- 막걸리
- 나들이
- 술
- 도리도리
- 전통주
- 아이랑
- C# 기초 강의
- 가볼만한 곳
- Visual Studio
- 도리도리 C#
- C# 강의
- 맛집
- 하이볼
- 게임
- 보드카
- WinForm
- 증류주
- 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 |