Статьи о почте

Новости

Все новости

Разное в мире IT

Все заметки

mailinfo.ru - Статьи о почте

Почта на web-интерфейсе

Прислал(а) Вадим Веденин [11 января 2002]

раздел: [Исходники]

Данная статья раскрывает процесс организации web-интерфейса почтовой службы корпоративного интернет-сайта. Решение данной проблемы представляет из себя более сложную и интересную задачу, посмотрите пример ее реализации.

Для создания web-интерфейса имелись следующие ресурсы:

  1. Почтовый сервер на базе Unix
  2. Web сервер IIS 4.0 на базе NT Server 4.0
  3. MS SQL 7.0
Так как уже был создан почтовый сервер на базе Unix для домена, в котором находиться сайт нашей компании, то очевидно следующее решение задачи:
  1. необходима ActiveX-компонента, работающая по POP3 протоколу с почтовым сервером для приема писем с почтового ящика
  2. необходима ActiveX-компонента, работающая по SMTP протоколу для отсылки писем
  3. необходима ActiveX-компонента, загружающая файлы на Web-сервер для отсылки почты
Причем необходимое условие для этих компонент - их бесплатность.

Для приема почты я использовал компоненту JMAILс сайта http://tech.dimac.net/, для отправки почты и загрузки файлов - компоненты сайта http://www.dundas.com/. Также был использован файловый менеджер SA-filemanager http://www.softartisans.com/.

Популярную компоненту CDO я не использовал из-за того, что она работает только с почтовыми серверами, основанными на IIS.

Прием почты

Для соединения с POP сервером был использован следующий код:

Set pop3 = Server.CreateObject( "JMail.POP3" )
pop3.Connect login, pass, pop_server

где login, pass - соответствующие параметры почтового сервера Unix, pop_server - переменная, содержащая адрес почтового сервера.

Чтение заголовков сообщений осуществляется следующим образом:

Response.Write("папка Inbox: "& pop3.Count & " сообщений")
Response.Write "
размер ящика " & pop3.Size & " байт "

i=1
if pop3.count <> 0 then

Response.Write "


"
pop3.DownloadHeaders

pageCount=int(pop3.Count/pageSize)
if pageCount=0 then pageCount=0 else
if pageCount*pageSize Response.Write "

"
for i=1 to pageCount
Response.Write "" _
& i & "
 "
next

Response.Write "
"
Response.Write " страница " & curpage+1 & " из " &
pageCount

Response.Write "

"
%>


bordercolor="DodgerBlue">





<%
for i=1 to pageSize
if curpage*pageSize+i>pop3.Count then exit for
%>



<%
next
%>

    от кого получено тема
value="<%=curpage*pageSize+i%>"> <%if inStr(1,
pop3.Messages.Item(curpage*pageSize+i).Charset,
"iso-8859-1",1)<>0 then
Response.Write " width=\'13\' height=\'14\'>"%>

<%Response.Write " " &
pop3.Messages.item(curpage*pageSize+i).From %>
<%=pop3.Messages.item(curpage*pageSize+i).Date%>>


href="read_message.asp?id=<%=curpage*pageSize+i%>">
<%
select case Request.QueryString("kode")
case "koi"

Response.Write(koiTowin1251(pop3.Messages.item(curpage*pageSize+i).Subject))
case "win"
Response.Write(pop3.Messages.item(curpage*pageSize+i).Subject)
case else
if
inStr(1,pop3.Messages.Item(curpage*pageSize+i).Charset,"koi8-r",1)
<>0
or
inStr(1,pop3.Messages.Item(curpage*pageSize+i).Charset,
"iso-8859-1",1) <>0 then
Response.Write(koiTowin1251(

pop3.Messages.item(curpage*pageSize+i).Subject))
else

Response.Write(pop3.Messages.item(curpage*pageSize+i).Subject)
end if
end select

%>


Почта на web-интерфейсе

И в конце страницы

<%
pop3.Disconnect
set pop3=Nothing
%>

При получении писем пришлось решать следующие проблемы: перекодировка сообщений, пришедших в кодировке KOI8-R, удаление сообщений, постраничное отображение полученных заголовков писем.

Проблема перекодировки сообщений возникает в случае, если сообщение приходит в кодировке koi8-r. Так как страница разработана в кодировке windows-1251, то вывод текста ссобщения без перекодировки привидет к тому что на странице будет текст в двух кодировках, что неприемлимо. Для этого создана функция перекодировки из koi8-r в windows-1251

function koiTowin1251(strkoi)

dim winArray
dim koiArray
dim i
dim result
dim indexFind

winArray="абвгдежзийклмнопрстуфхцчшщъыьэюя
АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ" koiArray="БВЧЗДЕЦЪЙКЛМНОПРТУФХЖИГЮЫЭЯЩШЬАС
вчздецъйклмнопртуфхжигюыэящшьас"

for i=1 to len(strkoi)
indexFind=instr(1,koiArray,mid(strkoi,i,1))
if indexFind<>0 then
result=result+mid(winArray,indexFind,1)
else
if mid(strkoi,i,1)=chr(13) then
i=i+1
result=result+"
"
else
result=result+mid(strkoi,i,1)
end if
end if
next

koiTowin1251=result
end function

Выбор между кодировками осуществляется при помощи передачи странице кода выбранной кодировки.

Для удаления сообщений достаточно использовать метод DeleteSingleMessage(id) компонеты JMail. Для этого необходимо следующее:

  1. при первом просмотре заголовков запомнить номер сообщения в тэге input
  2. при помощи кнопки submit передать это значение форме, содержащей серверный скрипт, удаляющий выбранное сообщение
Почтовое сообщение удаляется следующим скриптом:

if inStr(Request.ServerVariables("Request_Method"),
"POST")<>0 then

pop3.DownloadHeaders
for i=1 to Request.Form("checkDel").Count
pop3.DeleteSingleMessage(int(Request.Form("checkDel")(i)))
next
pop3.Disconnect
set pop3=Nothing
Response.Redirect "pop.asp"

End if

В данном скрипте проверяется , каким методом странице переданы параметры, и после этого сообщение удаляется.

Постраничное отображение полученных заголовков писем необходимо, если в почтовом ящике находится большое количество писем. Поэтому необходимо обеспечить отображение заголовков писем наборами по 10 штук ( например), и предоставить выбор нужного набора. Для этого странице передается параметр curpage в url старницы. Затем номер страницы инициализируется с помощью следующего кода

if len(Request.QueryString("curpage"))=0 then
curpage = 0
else
curpage= CInt (Request.QueryString("curpage"))
end if

Затем, на основе полученного значения и отображается выбранная страница. Выбор номера нужного набора сообщений я предоставляю следующим образом

pageCount=int(pop3.Count/pageSize)
if pageCount<>0 then
if pageCount*pageSizeend if

Response.Write "

"
for i=1 to pageCount
Response.Write " & i-1 & "\'>" & i & " "
next

Response.Write "
"
Response.Write " страница " & curpage+1 & " из " &
pageCount
Response.Write "

"

Чтение выбранного сообщения

При чтении сообщения возникает проблема кодировки, корректного отображения тела сообщения на asp странице, сохранения вложенных файлов на машину клиента.

Почта на web-интерфейсе

Метод решения проблемы кодировки описан выше.

Проблема отображения заключается в следующем: в теле сообщения переход на новую строку указан комбинацией специальных символов "перевод каретки" и "переход строки", которые игнорируются броузером. Для этого надо заменить все вхождения данных симолов на тэг
то есть комбинацию chr(13)chr(10) на "
" для этого создана функция convertForHTML

function convertForHTML(str)
dim result
dim i
result=""

for i=1 to len(str)
if mid(str,i,1)=chr(13) then
i=i+1
result=result+"
"
else
result=result+mid(str,i,1)
end if
next
convertForHTML=result
end function

Для сохранения вложений на машину клиента я использовал примеры с сайта http://www.aspfaqs.com/demos/StreamBinaryDemo.asp, http://prosto.pp.ru/Menu/Menu.htm и файловый менеджер SA-FileManager. Пример сохранения вложений

<%@ Language=VBScript%>

<%

dim id
dim attach
dim oFM
dim oBS
dim id_att
dim item
dim sbody
dim mess
dim i
on error resume next
login=Request.Cookies("login")
pass=Request.Cookies("pass")
fio=Request.Cookies("fio")

if len(login)= 0 and len(pass)=0 then Response.Redirect("index.asp")

Set pop3 = Server.CreateObject("JMail.POP3")

pop3.Connect login, pass, smtp_server
id=Request.QueryString("id")
id_att=Request.QueryString("id_att")

pop3.DownloadMessages
Set oFM = CreateObject("SoftArtisans.FileManager")

set attach=pop3.Messages(id).Attachments.Item(int(id_att))

if oFM.FileExists(Server.MapPath("temp") _
& "" & attach.Name)=true then oFM.DeleteFile
Server.MapPath("temp") _
& "" & attach.Name
attach.SaveToFile Server.MapPath("temp") & "" & attach.Name
Set oBS = oFM.OpenBinaryFile(Server.MapPath("temp") & "" &
attach.Name)

Response.Addheader "Content-Disposition", "attachment; filename="
& attach.Name
Response.ContentType=attach.ContentType

sbody=oBS.readAll

Response.BinaryWrite(sbody)
oBS.Close
oFM.DeleteFile Server.MapPath("temp") & "" & attach.Name
set oBS=nothing

set attach=nothing
set sbody=nothing

set oFM=nothing
pop3.Disconnect
set pop3=Nothing
set mess=nothing

if Err.number<> 0 then
%>

<% end if
%>

Скрипт, осуществляющий чтение выбранного сообщения










<%
if pop3.Messages.Item(id).Attachments.Count <> 0 then
%>




<%
end if
%>




тема
<%

select case Request.QueryString("kode")
case "koi"
Response.Write(koiTowin1251(pop3.Messages.item(id).Subject))
case "win"
Response.Write(pop3.Messages.item(id).Subject)
case else
if inStr(1,pop3.Messages.Item(id).Charset,"koi8-r",1) <>0
or
inStr(1,pop3.Messages.Item(id).Charset,"iso-8859-1",1) <>0 then

Response.Write(koiTowin1251(pop3.Messages.item(id).Subject))
else
Response.Write(pop3.Messages.item(id).Subject)
end if
end select

>

автор ответить на href="send_message.asp?toAddress=
<%=pop3.Messages.Item(id).From%>"><%
if len(pop3.Messages.item(id).FromName) <> 0 then

if inStr(1,pop3.Messages.Item(id).Charset,"koi8-r",1) <>0
or inStr(1,pop3.Messages.Item(id).Charset,"iso-8859-1",1)
<>0 then
Response.Write(koiTowin1251(pop3.Messages.item(id).FromName))
else

select case Request.QueryString("kode")
case "koi"

Response.Write(koiTowin1251(pop3.Messages.item(id).FromName))
case "win"

Response.Write(convertForHTML(pop3.Messages.item(id).FromName))
case else
if inStr(1,pop3.Messages.Item(id).Charset,"koi8-r",1)
<>0
or
inStr(1,pop3.Messages.Item(id).Charset,"iso-8859-1",1)
<>0 then

Response.Write(koiTowin1251(pop3.Messages.item(id).FromName))
else

Response.Write(convertForHTML(pop3.Messages.item(id).FromName))
end if
end select
end if
else
Response.Write " <" & pop3.Messages.item(id).From
& ">"
end if

%>

вложения <%
for i=0 to pop3.Messages.Item(id).Attachments.Count-1
%>
href="save_client.asp?id=<%=id%>&id_att=<%=i%>">
<%
Response.Write
pop3.Messages(id).Attachments.Item(i).Name _
& " " &
pop3.Messages.Item(id).Attachments.Item(i).Size _
& " байт

"

next
%>

<%\'=" type " &
pop3.Messages(id).Attachments.Item(0).ContentType%>

сообщение

<%

select case Request.QueryString("kode")
case "koi"
Response.Write(koiTowin1251(pop3.Messages.item(id).Body))
case "win"
Response.Write(convertForHTML(pop3.Messages.item(id).Body))
case else
if inStr(1,pop3.Messages.Item(id).Charset,"koi8-r",1) <>0
or inStr(1,pop3.Messages.Item(id).Charset,"iso-8859-1",1)
<>0 then

Response.Write(koiTowin1251(pop3.Messages.item(id).Body))
else

Response.Write(convertForHTML(pop3.Messages.item(id).Body))
end if
end select


%>

Отправка сообщений

Для отправки сообщений использованы Mailer- и Upload- компонета с сайта http://www.dundas.com/.

Пример отправки сообщения с вложенным файлом

if inStr(Request.ServerVariables("Request_Method"),"POST")<>0 then

Dim objMailer \'Mailer control
Dim objUpload
set objUpload = Server.CreateObject("Dundas.Upload.2")
set objMailer = Server.CreateObject("Dundas.Mailer")

objUpload.UseUniqueNames=false
objUpload.UseVirtualDir=true
objUpload.MaxUploadSize=maxUploadSize
objUpload.Save "temp"

\' послать

objMailer.SMTPRelayServers.Add smtp_server

\' посылаем тело письма
if objUpload.Files.count = 0 then

objMailer.CustomHeaders.Add "Content-Type:", "text/plain;charset=windows-1251"

objMailer.TOs.Add objUpload.Form("to")
objMailer.Subject = objUpload.Form("subject")
objMailer.Body = objUpload.Form("body")
objMailer.FromAddress = senderAddress
objMailer.FromName=senderName

else
\' посылаем вложение

\' Response.Write "
" & objUpload.Files.count
if objUpload.Files.count <> 0 then

objMailer.TOs.Add objUpload.Form("to")
objMailer.Subject = objUpload.Form("subject")
objMailer.FromAddress = senderAddress
objMailer.FromName=senderName

For Each Item in objUpload.Files
objMailer.Attachments.Add Item.Path,Item.OriginalPath, Item.ContentType,"BASE64","windows-1251"
Next

objMailer.Body = objUpload.Form("body")

set item=nothing

end if
end if

objMailer.SendMail
Set objMailer = Nothing
set objUpload=nothing
send_ok=True
end if

Таким образом, достаточно простой web- интерфейс для почты на сайте готов.

За рамками статьи я оставляю вопросы идентификации и регистрации пользователя, так как для этого использовались cookies и работы с БД, что достаточно просто. Адрес сайта, для которого была разработана данная система, не предоставляется, так как на момент написания статьи еще не была проведена работа по защите от несанкционированного доступа.