ASP.NET MVC Урок 1-F / ASP.NET MVC Урок A
.pdf$63 1(7 09& ǻȘȖȒ $ ǻȊȍȌȖȔȓȍȕȐȍ Ȑ ȘȈșșȣȓȒȈ tutorial
ASP*, .NET*
Цель урока Разобраться в отправлении писем и подтверждающих смс. MailNotify, использование конфигурационного файла. Рассылка через создание отдельного потока.
SmtpClient и MailNotify
При разработке сайта мы рано или поздно сталкиваемся с взаимодействием с электронной почтой, будь то активация пользователя, напоминание или сброс пароль, или создание рассылки. Определимся, что нам для этого нужно:
Класс, который будет рассылать письма
Конфигурация smtp берется из IConfig
Ошибки отправки письма протоколируются Наличие параметра, выключающего работу почты, дабы при работе с боевой базой клиентов не разослать какойто треш.
Создадим статический класс, назовем его MailSender (/Tools/Mail/MailSender.cs):
SXEOLF VWDWLF FODVV 0DLO6HQGHU
^
SULYDWH VWDWLF,&RQILJ BFRQILJ
SXEOLF VWDWLF,&RQILJ &RQILJ
^
JHW
^
LIBFRQILJ QXOO
^
BFRQILJ 'HSHQGHQF\5HVROYHU &XUUHQW *HW6HUYLFH ,&RQILJ!
`
UHWXUQBFRQILJ
`
`
SULYDWH VWDWLF1/RJ /RJJHU ORJJHU 1/RJ /RJ0DQDJHU *HW&XUUHQW&ODVV/RJJHU
SXEOLF VWDWLF YRLG 6HQG0DLO VWULQJHPDLOVWULQJVXEMHFWVWULQJERG\ 0DLO$GGUHVV PDLO$G GUHVV QXOO
^
WU\
^
LI&RQILJ (QDEOH0DLO
^
LIPDLO$GGUHVV QXOO
^
PDLO$GGUHVV QHZ0DLO$GGUHVV &RQILJ 0DLO6HWWLQJ 6PWS5HSO\ &RQILJ 0DLO6H WWLQJ 6PWS8VHU
`
0DLO0HVVDJH PHVVDJH QHZ0DLO0HVVDJH
PDLO$GGUHVV
QHZ0DLO$GGUHVV HPDLO
^
6XEMHFW VXEMHFW
%RG\(QFRGLQJ (QFRGLQJ 87)
%RG\ ERG\
,V%RG\+WPO WUXH
6XEMHFW(QFRGLQJ (QFRGLQJ 87)
`
6PWS&OLHQW FOLHQW QHZ6PWS&OLHQW
^
+RVW &RQILJ 0DLO6HWWLQJ 6PWS6HUYHU
3RUW &RQILJ 0DLO6HWWLQJ 6PWS3RUW
8VH'HIDXOW&UHGHQWLDOV IDOVH
(QDEOH6VO &RQILJ 0DLO6HWWLQJ (QDEOH6VO
&UHGHQWLDOV
QHZ1HWZRUN&UHGHQWLDO &RQILJ 0DLO6HWWLQJ 6PWS 8VHU1DPH
&RQILJ 0DLO6HWWLQJ 6PWS
3DVVZRUG
'HOLYHU\0HWKRG 6PWS'HOLYHU\0HWKRG 1HWZRUN
`
FOLHQW 6HQG PHVVDJH
`
HOVH
^
ORJJHU 'HEXJ(PDLO ^ ` ^ ` ?W 6XEMHFW ^ ` ^ ` %RG\ ^ `HPDLO (QYLURQP HQW 1HZ/LQH VXEMHFW (QYLURQPHQW 1HZ/LQH ERG\
`
`
FDWFK([FHSWLRQ H[
^
ORJJHU (UURU0DLO VHQG H[FHSWLRQH[ 0HVVDJH
`
`
`
Рассмотрим подробнее:
По необходимости, статически инициализируется IConfig из DependencyResolver
Если установлен флаг EnableMain, то начинаем работу с почтой, иначе просто письмо запишем в логфайл
Если MailAddress не указан, то он инициализируется по данным из конфига
SmtpClient инициализируется по данным из конфига
Тело письма – html
Кодировка – UTF8
Если при отправке произошла ошибка, то запишем Exception.Message в лог (тут можно и больше информации собирать, но пока нет необходимости).
Рассмотрим рассылку писем по шаблону. Создадим класс (тоже статический) NotifyMail (/Tools/Mail/NotifyMail.cs):
SXEOLF VWDWLF FODVV 1RWLI\0DLO
^
SULYDWH VWDWLF1/RJ /RJJHU ORJJHU 1/RJ /RJ0DQDJHU *HW&XUUHQW&ODVV/RJJHU
SULYDWH VWDWLF,&RQILJ BFRQILJ
SXEOLF VWDWLF,&RQILJ &RQILJ
^
JHW
^
LIBFRQILJ QXOO
^
BFRQILJ 'HSHQGHQF\5HVROYHU &XUUHQW *HW6HUYLFH ,&RQILJ!
`
UHWXUQBFRQILJ
`
`
SXEOLF VWDWLF YRLG 6HQG1RWLI\ VWULQJWHPSODWH1DPHVWULQJHPDLO
)XQFVWULQJ VWULQJ! VXEMHFW
)XQFVWULQJ VWULQJ! ERG\
^
YDUWHPSODWH &RQILJ 0DLO7HPSODWHV )LUVW2U'HIDXOW S !VWULQJ&RPSDUH S 1DPH WHPSOD WH1DPHWUXH
LIWHPSODWH QXOO
^
ORJJHU (UURU&DQ W ILQG WHPSODWHWHPSODWH1DPH
`
HOVH
^
0DLO6HQGHU 6HQG0DLO HPDLO
VXEMHFW ,QYRNH WHPSODWH 6XEMHFW
ERG\ ,QYRNH WHPSODWH 7HPSODWH
`
`
`
Аналогично получаем конфиг. При рассылке мы указываем для неё, и дальше используем Func<string,string> для формирования темы и тела письма.
Уведомим пользователя о регистрации, используя шаблон Register из Web.config:
DGG QDPH 5HJLVWHU VXEMHFW Ɋɟɝɢɫɬɪɚɰɢɹ ɧɚ ^ ` WHPSODWH Ɂɞɪɚɜɫɬɜɭɣɬɟ EU ! EU ! ɉɟɪɟɣɞɢɬɟ ɩɨ
ɫɫɵɥɤɟ D KUHI KWWS ^ ` 8VHU$FWLYDWH ^ ` !KWWS ^ ` 8VHU$FWLYDWH ^ ` D! ɱɬɨɛɵ ɩɨɞɬɜɟɪɬɢɬ
ɶ ɫɜɨɣ ɩɨɱɬɨɜɵɣ ɹɳɢɤ EU ! EU !ɋ ɭɜɚɠɟɧɢɟɦ ɤɨɦɚɧɞɚ D KUHI KWWS ^ ` !^ ` D!!
Заметим, как необходимо экранировать htmlтеги, чтобы правильно сделать шаблон. Нужно учитывать зависимость между шаблоном для string.Format() и количеством параметров. В UserController.cs при регистрации добавим (/Areas/Default/Controllers/UserController.cs:Register):
5HSRVLWRU\ &UHDWH8VHU XVHU
1RWLI\0DLO 6HQG1RWLI\5HJLVWHUXVHU (PDLO
VXEMHFW !VWULQJ)RUPDW VXEMHFW +RVW1DPH
ERG\ !VWULQJ)RUPDW ERG\ +RVW1DPH
UHWXUQ5HGLUHFW7R$FWLRQ,QGH[
HostName мы добавили в инициализации BaseController (/Controllers/BaseController.cs):
SXEOLF VWDWLF VWULQJ+RVW1DPH VWULQJ(PSW\ SURWHFWHG RYHUULGH YRLG ,QLWLDOL]H6\VWHP :HE 5RXWLQJ 5HTXHVW&RQWH[W UHTXHVW&RQWH[W
^
LIUHTXHVW&RQWH[W +WWS&RQWH[W 5HTXHVW 8UO QXOO
^
+RVW1DPH UHTXHVW&RQWH[W +WWS&RQWH[W 5HTXHVW 8UO$XWKRULW\
` «
Регистрируемся, и на нашу почту приходит письмо:
Более сложный случай
Всё это хорошо, но если нам необходимо рассылку с кучей акционных предложений, то данный формат нам не подойдет. Вопервых, сложно подобный шаблон задавать в Web.config, вовторых, количество параметров не известно. Как и обычные htmlшаблоны, шаблон письма было бы чудесно задать во View. Что ж, рассмотрим библиотеку ActionMailer (http://nuget.org/packages/ActionMailer):
30! ,QVWDOO 3DFNDJH$FWLRQ0DLOHU
6XFFHVVIXOO\ LQVWDOOHG $FWLRQ0DLOHU
6XFFHVVIXOO\ DGGHG $FWLRQ0DLOHUWR /HVVRQ3URMHFW 0RGHO
Отнаследуем MailController от MailerBase:
SXEOLF FODVV 0DLO&RQWUROOHU 0DLOHU%DVH
^
SXEOLF(PDLO5HVXOW6XEVFULSWLRQ VWULQJPHVVDJHVWULQJHPDLO
^
7R$GG HPDLO
6XEMHFW Ɋɚɫɫɵɥɤɚ
0HVVDJH(QFRGLQJ (QFRGLQJ 87)
UHWXUQ(PDLO6XEVFULSWLRQPHVVDJH
`
`
Добавим Subscription.html.cshtml View (/Areas/Default/Views/Mail/Subscription.html.cshtml):
#PRGHO VWULQJ
#^
/D\RXW QXOO
`
'2&7<3( KWPO 38%/,& : & '7' ;+70/ 7UDQVLWLRQDO (1 KWWS ZZZ Z RUJ 75 [KWPO '7' [
KWPO WUDQVLWLRQDO GWG !KWPO!
KHDG!
PHWD KWWS HTXLY &RQWHQW 7\SH FRQWHQW WH[W KWPO FKDUVHW 87)!
KHDG!
ERG\!
GLY!
K!#0RGHOK!
GLY!ERG\!KWPO!
Добавляем в Web.config конфигурацию для работы с почтой (Web.config):
V\VWHP QHW!
PDLO6HWWLQJV!
VPWS GHOLYHU\0HWKRG 1HWZRUN IURP O[QGUSHWURY#JPDLO FRP!
QHWZRUN KRVW VPWS JPDLO FRP SRUW XVHU1DPH O[QGUSHWURY SDVVZRUG HQDEOH 6VO WUXH!
VPWS!
PDLO6HWWLQJV!V\VWHP QHW!
И создаем в UserController.cs тестовый метод (/Areas/Default/Controllers/UserController.cs):
>$XWKRUL]H@
SXEOLF $FWLRQ5HVXOW6XEVFULSWLRQ7HVW
^
YDUPDLO&RQWUROOHU QHZ0DLO&RQWUROOHU
YDUHPDLO PDLO&RQWUROOHU 6XEVFULSWLRQɉɪɢɜɟɬ ɦɢɪ&XUUHQW8VHU (PDLO
HPDLO 'HOLYHU
UHWXUQ&RQWHQW2.
`
Запускаем:
localhost/User/SubscriptionTest — и получаем на почту письмо.
Рассмотрим пример получения текста письма в строку. Для этого понадобится StreamReader (/Areas/Default/Controllers/UserController.cs):
>$XWKRUL]H@
SXEOLF $FWLRQ5HVXOW6XEVFULSWLRQ6KRZ
^
YDUPDLO&RQWUROOHU QHZ0DLO&RQWUROOHU
YDUHPDLO PDLO&RQWUROOHU 6XEVFULSWLRQɉɪɢɜɟɬ ɦɢɪ&XUUHQW8VHU (PDLO
XVLQJ YDUUHDGHU QHZ6WUHDP5HDGHU HPDLO 0DLO$OWHUQDWH9LHZV> @ &RQWHQW6WUHDP
^
YDUFRQWHQW UHDGHU 5HDG7R(QG
UHWXUQ&RQWHQW FRQWHQW
`
UHWXUQ QXOO
`
В content уже есть сформированная страница. Запускаем: localhost/User/SubscriptionShow
SmsNotify
В этой главе рассмотрим взаимодействие с помощью смс, а не только почты. Но есть ньюанс – доступ к рассылке предоставляется отдельными сервисами, и тут мы рассмотрим только основные принципынаписания модуля для работы с SMSпровайдерами на примере работы с unisender.ru.
Создадим класс настроек по типу MailSetting (/Global/Config/SmsSetting.cs):
SXEOLF FODVV 6PV6HWWLQJ &RQILJXUDWLRQ6HFWLRQ
^
>&RQILJXUDWLRQ3URSHUW\DSL.H\,V5HTXLUHG WUXH@
SXEOLF VWULQJ $3,.H\
^
JHW
^
UHWXUQ WKLV>DSL.H\@DV VWULQJ
`
VHW
^
WKLV>DSL.H\@ YDOXH
`
`
>&RQILJXUDWLRQ3URSHUW\VHQGHU,V5HTXLUHG WUXH@
SXEOLF VWULQJ6HQGHU
^
JHW
^
UHWXUQ WKLV>VHQGHU@DV VWULQJ
`
VHW
^
WKLV>VHQGHU@ YDOXH
`
`
>&RQILJXUDWLRQ3URSHUW\WHPSODWH8UL,V5HTXLUHG WUXH@
SXEOLF VWULQJ7HPSODWH8UL
^
JHW
^
UHWXUQ WKLV>WHPSODWH8UL@DV VWULQJ
`
VHW
^
WKLV>WHPSODWH8UL@ YDOXH
`
`
`
Зададим в Web.Config (Web.config):
FRQILJ6HFWLRQV!
«
VHFWLRQ QDPH VPV&RQILJ W\SH /HVVRQ3URMHFW *OREDO &RQILJ 6PV6HWWLQJ /HVVRQ3URMHFW!FRQILJ6HFWLRQV!
«
VPV&RQILJ
DSL.H\
VHQGHU 'DGG\
WHPSODWH8UL KWWS DSL XQLVHQGHU FRP UX DSL VHQG6PV
!
FRQILJXUDWLRQ!
Создадим класс SmsSender (/Tools/Sms/SmsSender.cs):
SXEOLF VWDWLF FODVV 6PV6HQGHU
^
SULYDWH VWDWLF,&RQILJ BFRQILJ
SXEOLF VWDWLF,&RQILJ &RQILJ
^
JHW
^
LIBFRQILJ QXOO
^
BFRQILJ 'HSHQGHQF\5HVROYHU &XUUHQW *HW6HUYLFH ,&RQILJ!
`
UHWXUQBFRQILJ
`
`
SULYDWH VWDWLF1/RJ /RJJHU ORJJHU 1/RJ /RJ0DQDJHU *HW&XUUHQW&ODVV/RJJHU
SXEOLF VWDWLF VWULQJ 6HQG6PV VWULQJSKRQHVWULQJWH[W
^
LI VWULQJ,V1XOO2U:KLWH6SDFH &RQILJ 6PV6HWWLQJ$3,.H\
^
UHWXUQ*HW5HTXHVW SKRQH &RQILJ 6PV6HWWLQJ 6HQGHU WH[W
`
HOVH
^
ORJJHU 'HEXJ6PV ?W 3KRQH ^ ` %RG\ ^ `SKRQH WH[W
UHWXUQ 6XFFHVV
`
`
SULYDWH VWDWLF VWULQJ *HW5HTXHVW VWULQJSKRQHVWULQJVHQGHUVWULQJWH[W
^
WU\
^
+WWS:HE5HTXHVW ZHE5HTXHVW +WWS:HE5HTXHVW :HE5HTXHVW &UHDWH &RQILJ 6PV6HWWLQJ 7 HPSODWH8UL
LPSRUWDQW RWKHUZLVH WKH VHUYLFH FDQ W GHVLULDOVH \RXU UHTXHVW SURSHUO\
ZHE5HTXHVW &RQWHQW7\SH DSSOLFDWLRQ [ ZZZ IRUP XUOHQFRGHG
ZHE5HTXHVW 0HWKRG 3267
ZHE5HTXHVW .HHS$OLYH IDOVH
ZHE5HTXHVW 3UH$XWKHQWLFDWH IDOVH
VWULQJSRVW'DWD IRUPDW MVRQ DSLBNH\ &RQILJ 6PV6HWWLQJ$3,.H\ SKRQH SKRQH
VHQGHU VHQGHU WH[W +WWS8WLOLW\ 8UO(QFRGH WH[W
YDUDVFLL QHZ $6&,,(QFRGLQJ
E\WH>@ E\WH$UUD\ DVFLL *HW%\WHV SRVW'DWD
ZHE5HTXHVW &RQWHQW/HQJWK E\WH$UUD\ /HQJWK
6WUHDP GDWD6WUHDP ZHE5HTXHVW *HW5HTXHVW6WUHDP
GDWD6WUHDP :ULWH E\WH$UUD\ E\WH$UUD\ /HQJWK
GDWD6WUHDP &ORVH
:HE5HVSRQVH ZHE5HVSRQVH ZHE5HTXHVW *HW5HVSRQVH
6WUHDP UHVSRQFH6WUHDP ZHE5HVSRQVH *HW5HVSRQVH6WUHDP
(QFRGLQJ HQF 6\VWHP 7H[W (QFRGLQJ 87)
6WUHDP5HDGHU OR5HVSRQVH6WUHDP QHZ
6WUHDP5HDGHU ZHE5HVSRQVH *HW5HVSRQVH6WUHDP HQF
VWULQJ5HVSRQVH OR5HVSRQVH6WUHDP 5HDG7R(QG
UHWXUQ5HVSRQVH
`
FDWFK([FHSWLRQ H[
^
ORJJHU (UURU([FHSWLRQɈɲɢɛɤɚ ɩɪɢ ɨɬɩɪɚɜɤɟ 606H[
UHWXUQ Ɉɲɢɛɤɚ ɩɪɢ ɨɬɩɪɚɜɤɟ 606
`
`
`
Результат приходит типа:
^UHVXOW^FXUUHQF\ 58% SULFH VPVBLG B``
Его можно разобрать и проанализировать.
В следующем уроке мы рассмотрим, как работать с json.
Отдельный поток
Если мы рассылаем электронную почту большому количеству людей, то обработка может занять много времени. Для этого я пользуюсь следующим принципом:
Создаем отдельный поток, который проверяет, если ли исходящие письма готовые к отправке
При создании рассылки создаются письма и записываются в БД
Поток проверяет состояние БД на наличие писем
Письма извлекаются из БД последовательно (письмо может удалиться, может только обнулить содержимое письма (чтоб сэкономить размер БД).
Письмо отправляется. Возвращается к проверке.
Отдельный поток запускается в Application_Start. Таймер устанавливается на повторение через 1