powered by simpleCommunicator - 2.0.54     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / А про IMAP не разжуете?
40 сообщений из 40, показаны все 2 страниц
А про IMAP не разжуете?
    #38962162
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Никогда с IMAP дела не имел, тут решил пощупать.
Почитав чуть, понял что есть де папки на сервере, они синхронизируются с папками на клиенте (можно с несколькими клиентами одновременно).
Взял Outlook Express (на тестовом компе что под рукой), настроил его на gmail по IMAP. Принцип вроде понял.

Неясно следующее: (пробовал несколько раз)
1) Я отправил себе на gmail письмо.
2) Я его получил по IMAP
3) Я на него смотрел, смотрел в настройки OE, удалял что только ни делал, правка - очистить удаленные сообщения и т.п.
4) Все равно оно всегда скачивается по POP3 на рабочем (другом) компе. (Я не сумел его жестко получить по IMAP).

Мне имеет смысл м.б. использовать IMAP в своей проге (как альтернативу POP3) только при выполнении след. условий:
1) Я письмо получил (по IMAP)
2) Я письмо на сервере удалил
3) Никто ни я, ни кто другой, ни по IMAP, ни по POP3 больше это письмо получить не может.

(Т.е. чтоб также как при обычной работе по POP3).

Возможно? Или идеология протокола не позволяет? (Я не сумел это воспроизвести через OE+IMAP -надо без условий, что ящик надо как-то настраивать, сервера де разные).

Если все-таки что-то не допонял и это однозначно делается, то

1) Смысл в реализацию оного влезать есть?
2) Как в .Net это реализуется? Еще сложнее чем POP3 (+SSL) или такого же уровня сложности?
3) Примеры есть? Нормальные, типа как я с POP3 на днях нарыл.
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38962192
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77 1) Я письмо получил (по IMAP)Это бессмыслица, IMAP - протокол управления сообщениями в собственном почтовом ящике. В ящик письма приходят исключительно по SMTP.

Дмитрий77 Возможно? Или идеология протокола не позволяет?Можно, позволяет.

Код: vbnet
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.
Public Enum Proto
    pSMTP = 1
    pIMAP = 2
End Enum

Public Enum POP3States
    POP3_Connect = 1
    POP3_USER = 2
    POP3_PASS = 3
    POP3_STAT = 4
    POP3_TOP = 5
    POP3_DELE = 6
    POP3_QUIT = 7
    POP3_LIST = 8
    POP3_VeryQUIT = 9
    IMAP_EXPUNGE = 10
    IMAP_COPY = 11
    POP3_RETR = 12
End Enum

Public Type WSState
    State As POP3States
    StateStat As Boolean
    AccountID As Long
    SpamCount As Integer
    MailCount As Integer
    MessagesCount As Integer
    Protocol As Proto
    Login As String
    Pass As String
    CurrentMsg As Integer
    BufferString As String
    IMAPStep As Integer
    Stored As Boolean
    Error As Boolean
    Account As String
    IMAPMsgs() As String
    RsDeleted As ADODB.Recordset
    RETR As Long
    Server As String
End Type

Public Sub DataArrivalIMAP(Winsock1 As Winsock, ByVal bytesTotal As Long)
Dim m_oMessage As CMessage
Dim strData As String
Dim strData1 As String
Dim IP As String
Dim r As Boolean
Dim s() As String
Dim X As Integer
Dim lSize As Long
    Winsock1.GetData strData1
    s = Split(strData1, vbCrLf)
    strData = s(UBound(s) - 1)
    With m_States(Winsock1.Index)
        If .State = POP3_TOP Then
            Debug.Print strData1 'strData & vbCrLf
        Else
            Debug.Print strData1
        End If
        If Mid$(strData, InStr(strData, " ") + 1, 2) = "OK" Or Mid$(s(0), InStr(s(0), " ") + 1, 2) = "OK" Then
            .IMAPStep = .IMAPStep + 1
            Select Case .State
                Case POP3_Connect
                    .MessagesCount = 0
                    .IMAPStep = 1
                    .State = POP3_USER
                    Winsock1.SendData "A" & .IMAPStep & " LOGIN " & .Login & " " & .Pass & vbCrLf
                    'Debug.Print "A" & .IMAPStep & " LOGIN " & rsAccounts!login & " " & rsAccounts!Pass & vbCrLf
                Case POP3_USER
                    .State = POP3_STAT
                    Winsock1.SendData "A" & .IMAPStep & " SELECT INBOX" & vbCrLf
                    'Debug.Print "SELECT INBOX"
                Case POP3_STAT
                    .State = POP3_LIST
                    Debug.Print ">>>> "; "A" & .IMAPStep & " SEARCH UNSEEN"
                    Winsock1.SendData "A" & .IMAPStep & " SEARCH UNSEEN" & vbCrLf
                    'Debug.Print "SEARCH ALL"
                Case POP3_LIST
                    .IMAPMsgs = Split(Mid$(s(0), InStr(s(0), "SEARCH") + 7), " ")
                    .MessagesCount = UBound(.IMAPMsgs) + 1
                    If .MessagesCount > 0 Then
                        .State = POP3_TOP
                        .CurrentMsg = 0 '.MessagesCount
                        .MailCount = .MessagesCount
                        Debug.Print ">>>> "; "A" & .IMAPStep & " FETCH " & .IMAPMsgs(.CurrentMsg) & " (FLAGS RFC822.SIZE RFC822.HEADER)"
                        Winsock1.SendData "A" & .IMAPStep & " FETCH " & .IMAPMsgs(.CurrentMsg) & " body[header]" & vbCrLf ' " (FLAGS RFC822.SIZE RFC822.HEADER)" & vbCrLf
                    Else
                        .State = POP3_QUIT
                        Winsock1.SendData "A" & .IMAPStep & " LOGOUT" & vbCrLf
                    End If
                Case POP3_TOP
                        For X = 1 To UBound(s) - 4
                            IP = IP & s(X) & vbCrLf
                        Next
                        IP = IP & vbCrLf
                        Set m_oMessage = New CMessage
                        m_oMessage.CreateFromText IP
                        'Debug.Print m_oMessage.Subject
                        Winsock1.SendData CheckMsg(m_oMessage, Winsock1.Index)
                Case POP3_QUIT
                    Winsock1.Close
                    .State = POP3_VeryQUIT
                Case POP3_DELE
                    .CurrentMsg = .CurrentMsg + 1
                    If .CurrentMsg = .MessagesCount Then
                        '.State = IMAP_EXPUNGE
                        'Winsock1.SendData "A" & .IMAPStep & " EXPUNGE" & vbCrLf
                        .State = POP3_QUIT
                        Winsock1.SendData "A" & .IMAPStep & " LOGOUT" & vbCrLf
                    Else
                        .State = POP3_TOP
                        Winsock1.SendData "A" & .IMAPStep & " FETCH " & .IMAPMsgs(.CurrentMsg) & " (flags RFC822.SIZE RFC822.HEADER)" & vbCrLf
                    End If
                Case IMAP_EXPUNGE
                    .State = POP3_QUIT
                    Winsock1.SendData "A" & .IMAPStep & " LOGOUT" & vbCrLf
                Case IMAP_COPY
                    .CurrentMsg = .CurrentMsg + 1
                    If .CurrentMsg = .MessagesCount Then
                        .State = POP3_VeryQUIT 'POP3_QUIT
                        Winsock1.SendData "A" & .IMAPStep & " LOGOUT" & vbCrLf 'EXPUNGE
                    Else
                        .State = POP3_TOP
                        Debug.Print ">>>> "; "A" & .IMAPStep & " FETCH " & .IMAPMsgs(.CurrentMsg) & " (FLAGS RFC822.SIZE RFC822.HEADER)"
                        Winsock1.SendData "A" & .IMAPStep & " FETCH " & .IMAPMsgs(.CurrentMsg) & " body[header]" & vbCrLf '& " (flags RFC822.SIZE RFC822.HEADER)" & vbCrLf
                    End If
                    'Winsock1.SendData "A" & .IMAPStep & " SEARCH UNSEEN" & vbCrLf
                '    .State = POP3_DELE
                '    Winsock1.SendData "A" & .IMAPStep & " STORE " & .IMAPMsgs(.CurrentMsg) & " +FLAGS \Deleted \flagged" & vbCrLf
            End Select
        ElseIf InStr(strData, " NO ") = 0 And Mid$(s(0), 1, 1) = "*" Then
            .BufferString = .BufferString & strData
        Else
            frmReport.ctlProgress1.ErrDesc(Winsock1.Index) = LoadEnumString(msg_ErrorDD) & strData
            Winsock1.SendData "A" & .IMAPStep & " EXPUNGE" & vbCrLf
            .State = POP3_QUIT
            .Error = True
        End If
    End With
End Sub


В примере понатыкано POP3 просто потому что было лень городить еще один Enum, использовал один и для POP3 и для IMAP.
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38962199
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще кусок
Код: vbnet
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.
Private Function CheckMsg(m_oMessage As CMessage, WSIndex As Integer) As String
Dim ID As Long
Dim rs As ADODB.Recordset
Dim csResult As CheckState
    On Error GoTo errh
    With m_States(WSIndex)

'вырезано лишнее

        If m_oMessage.Status > rNotChecked And StaDelete(m_oMessage.Status) Then

'вырезано лишнее

            If StaSave(m_oMessage.Status) Then
                If .State = POP3_TOP Then
                    .State = POP3_RETR
                    .RETR = 1
                    CheckMsg = "RETR " & .CurrentMsg & vbCrLf
                    Exit Function
                Else
                    rs!Message = m_oMessage.MsgBytes
                End If
            End If
            If .RsDeleted.EOF Then rs.UpdateBatch
        End If
        'GoTo skip
        If m_oMessage.Deleted Then
            If .Protocol = pSMTP Then
                .State = POP3_DELE
                CheckMsg = "DELE " & .CurrentMsg & vbCrLf
            Else
                '.State = IMAP_COPY
                .State = POP3_DELE
                CheckMsg = "A" & .IMAPStep & " COPY " & .IMAPMsgs(.CurrentMsg) & " Trash" & vbCrLf
                'Winsock1.SendData "A" & .IMAPStep & " STORE " & .IMAPMsgs(.CurrentMsg) & " +FLAGS \Deleted \flagged" & vbCrLf
                'CheckMsg =  "A" & .IMAPStep & " STORE " & .IMAPMsgs(.CurrentMsg) & " +FLAGS \Deleted \flagged" & vbCrLf
            End If
        Else
skip:
            If .Protocol = pSMTP Then
                If .CurrentMsg = .MessagesCount Then
                    .StateStat = True
                    .State = POP3_STAT
                    CheckMsg = "STAT" & vbCrLf
                Else
                    .CurrentMsg = .CurrentMsg + 1
                    If FastMode Then
                        .State = POP3_TOP
                        CheckMsg = "TOP " & .CurrentMsg & " 0" & vbCrLf
                    Else
                        .State = POP3_RETR
                        CheckMsg = "RETR " & .CurrentMsg & vbCrLf
                    End If
                End If
            Else
                'CheckMsg = "A" & .IMAPStep & " FETCH " & .IMAPMsgs(.CurrentMsg) & " (flags RFC822.SIZE RFC822.HEADER)" & vbCrLf
                Debug.Print ">>>> A" & .IMAPStep & " STORE " & .IMAPMsgs(.CurrentMsg) & " -FLAGS (\Seen)"
                CheckMsg = "A" & .IMAPStep & " STORE " & .IMAPMsgs(.CurrentMsg) & " -FLAGS (\Seen)" & vbCrLf
                .State = IMAP_COPY
            End If
        End If
        .BufferString = ""
    End With
    frmReport.AddMessage m_oMessage
    Exit Function
errh:
    frmReport.ctlProgress1.ErrDesc(WSIndex) = LoadEnumString(, "ProgramError") & "CheckMsg - " & Err.Description
    Exit Function
    Resume
End Function
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38962291
carrotik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77,

.. посмотрите MailSystem.NET, если хотите использовать готовую библиотеку ... Если самому писать, то у меня вышло строчек на тысчонку кода (в варианте ASP.NET webmail) ... для вин-форм может быть поменьше .... хотя ...
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963011
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
carrotikесли хотите использовать готовую библиотеку ...
Ясно дело не хочу.

Antonariy,
я так понимаю из твоего кода и твоих комментариев, что принцип общения с POP3 и IMAP абсолютно одинаков:
команда ->
<- ответ
анализ ответа
При необходимости оборачиваем в SSL-stream (вот здесь чувствуются преимущества .Net).
Так?

Т.е. получается что если класс для POP3 я передрал/написал (ага, 1009 строк):

Код: vbnet
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.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
506.
507.
508.
509.
510.
511.
512.
513.
514.
515.
516.
517.
518.
519.
520.
521.
522.
523.
524.
525.
526.
527.
528.
529.
530.
531.
532.
533.
534.
535.
536.
537.
538.
539.
540.
541.
542.
543.
544.
545.
546.
547.
548.
549.
550.
551.
552.
553.
554.
555.
556.
557.
558.
559.
560.
561.
562.
563.
564.
565.
566.
567.
568.
569.
570.
571.
572.
573.
574.
575.
576.
577.
578.
579.
580.
581.
582.
583.
584.
585.
586.
587.
588.
589.
590.
591.
592.
593.
594.
595.
596.
597.
598.
599.
600.
601.
602.
603.
604.
605.
606.
607.
608.
609.
610.
611.
612.
613.
614.
615.
616.
617.
618.
619.
620.
621.
622.
623.
624.
625.
626.
627.
628.
629.
630.
631.
632.
633.
634.
635.
636.
637.
638.
639.
640.
641.
642.
643.
644.
645.
646.
647.
648.
649.
650.
651.
652.
653.
654.
655.
656.
657.
658.
659.
660.
661.
662.
663.
664.
665.
666.
667.
668.
669.
670.
671.
672.
673.
674.
675.
676.
677.
678.
679.
680.
681.
682.
683.
684.
685.
686.
687.
688.
689.
690.
691.
692.
693.
694.
695.
696.
697.
698.
699.
700.
701.
702.
703.
704.
705.
706.
707.
708.
709.
710.
711.
712.
713.
714.
715.
716.
717.
718.
719.
720.
721.
722.
723.
724.
725.
726.
727.
728.
729.
730.
731.
732.
733.
734.
735.
736.
737.
738.
739.
740.
741.
742.
743.
744.
745.
746.
747.
748.
749.
750.
751.
752.
753.
754.
755.
756.
757.
758.
759.
760.
761.
762.
763.
764.
765.
766.
767.
768.
769.
770.
771.
772.
773.
774.
775.
776.
777.
778.
779.
780.
781.
782.
783.
784.
785.
786.
787.
788.
789.
790.
791.
792.
793.
794.
795.
796.
797.
798.
799.
800.
801.
802.
803.
804.
805.
806.
807.
808.
809.
810.
811.
812.
813.
814.
815.
816.
817.
818.
819.
820.
821.
822.
823.
824.
825.
826.
827.
828.
829.
830.
831.
832.
833.
834.
835.
836.
837.
838.
839.
840.
841.
842.
843.
844.
845.
846.
847.
848.
849.
850.
851.
852.
853.
854.
855.
856.
857.
858.
859.
860.
861.
862.
863.
864.
865.
866.
867.
868.
869.
870.
871.
872.
873.
874.
875.
876.
877.
878.
879.
880.
881.
882.
883.
884.
885.
886.
887.
888.
889.
890.
891.
892.
893.
894.
895.
896.
897.
898.
899.
900.
901.
902.
903.
904.
905.
906.
907.
908.
909.
910.
911.
912.
913.
914.
915.
916.
917.
918.
919.
920.
921.
922.
923.
924.
925.
926.
927.
928.
929.
930.
931.
932.
933.
934.
935.
936.
937.
938.
939.
940.
941.
942.
943.
944.
945.
946.
947.
948.
949.
950.
951.
952.
953.
954.
955.
956.
957.
958.
959.
960.
961.
962.
963.
964.
965.
966.
967.
968.
969.
970.
971.
972.
973.
974.
975.
976.
977.
978.
979.
980.
981.
982.
983.
984.
985.
986.
987.
988.
989.
990.
991.
992.
993.
994.
995.
996.
997.
998.
999.
1000.
1001.
1002.
1003.
1004.
1005.
1006.
1007.
1008.
1009.
Imports System.Net.Sockets
Imports System.Net.Security
Imports System.IO
Imports System.Text

Module ModulePop3

  Public Sub GetMail(ByVal m_PopServer As String, ByVal m_User As String, ByVal m_Password As String, _
   Optional ByVal m_ServerPort As Integer = 110, Optional ByVal m_useSSL As Boolean = False, _
   Optional ByVal m_DeleteEmails As Boolean = True, Optional ByVal m_SaveDir As String = vbNullString, _
   Optional ByVal m_SaveMailPrefix As String = "MSG", Optional ByVal m_SaveMailExt As String = ".eml", _
   Optional ByVal m_TraceFunction As Pop3.TraceHandler = Nothing, Optional ByVal m_TestMode As Boolean = False)

    If m_TraceFunction IsNot Nothing AndAlso m_TestMode = False Then m_TraceFunction("-------------------------")
    Try
      ' prepare pop client
      Dim POP3Client As Pop3.cPop3MailClient = _
       New Pop3.cPop3MailClient(m_PopServer, m_ServerPort, m_useSSL, m_User, m_Password)
      POP3Client.IsAutoReconnect = True

      'if tracing needed
      If m_TraceFunction IsNot Nothing Then AddHandler POP3Client.Trace, m_TraceFunction

      POP3Client.ReadTimeout = 60000 'give pop server 60 seconds to answer

      'establish connection
      POP3Client.Connect()

      'get mailbox statistics
      Dim NumberOfMails As Integer, MailboxSize As Integer
      POP3Client.GetMailboxStats(NumberOfMails, MailboxSize)

      If m_TestMode Then
        'get a list of mails
        Dim EmailIds As New List(Of Integer)
        POP3Client.GetEmailIdList(EmailIds)

        'get a list of unique mail ids
        Dim EmailUids As New List(Of Pop3.EmailUid)
        POP3Client.GetUniqueEmailIdList(EmailUids)

        'only show info
        If NumberOfMails > 0 Then
          For i As Integer = 1 To NumberOfMails
            'get email size
            POP3Client.GetEmailSize(i)
          Next
        End If

        'ping server
        POP3Client.NOOP()

      Else

        'get emails
        If NumberOfMails > 0 Then

          If Strings.Len(m_SaveDir) = 0 OrElse IO.Directory.Exists(m_SaveDir) = False Then _
           m_SaveDir = Application.StartupPath
          If Strings.Len(m_SaveMailPrefix) = 0 Then m_SaveMailPrefix = "MSG"
          If Strings.Len(m_SaveMailExt) = 0 Then m_SaveMailExt = ".eml"
          If Strings.Left(m_SaveMailExt, 1) <> "." Then m_SaveMailExt = "." & m_SaveMailExt

          For i As Integer = 1 To NumberOfMails
            'get email size
            POP3Client.GetEmailSize(i)

            'get email
            Dim Email As String = ""
            POP3Client.GetRawEmail(i, Email)
            If Strings.Len(Email) > 0 Then
              Dim fToSave As String = GetNextEmailFileName(m_SaveDir, m_SaveMailPrefix, m_SaveMailExt)
              Try : IO.File.WriteAllText(fToSave, Email, System.Text.Encoding.ASCII) : Catch : End Try
            End If

            'delete email
            If m_DeleteEmails Then POP3Client.DeleteEmail(i)
          Next
        End If
      End If

      'close connection
      POP3Client.Disconnect()

    Catch ex As Exception
      If m_TraceFunction IsNot Nothing Then
        m_TraceFunction("Run Time Error Occured:")
        m_TraceFunction(ex.Message)
        m_TraceFunction(ex.StackTrace)
      End If
    End Try
    If m_TraceFunction IsNot Nothing AndAlso m_TestMode = False Then m_TraceFunction("-------------------------")

  End Sub

  Private Function GetNextEmailFileName(ByVal path As String, ByVal pref As String, ByVal ext As String) As String
    Dim tmp_name As String
    Dim i As Integer = 0
    Do
      i = i + 1
      tmp_name = IO.Path.Combine(path, pref & i.ToString & ext)
      If IO.File.Exists(tmp_name) = False Then Return tmp_name
    Loop
  End Function

End Module

Namespace Pop3
  ' Supporting classes and structs
  ' ==============================

  ''' <summary>
  ''' Combines Email ID with Email UID for one email
  ''' The POP3 server assigns to each message a unique Email UID, which will not change for the life time
  ''' of the message and no other message should use the same.
  ''' 
  ''' Exceptions:
  ''' Throws Pop3Exception if there is a serious communication problem with the POP3 server, otherwise
  ''' 
  ''' </summary>
  Public Structure EmailUid
    ''' <summary>
    ''' used in POP3 commands to indicate which message (only valid in the present session)
    ''' </summary>
    Public EmailId As Integer
    ''' <summary>
    ''' Uid is always the same for a message, regardless of session
    ''' </summary>
    Public Uid As String

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="EmailId"></param>
    ''' <param name="Uid"></param>
    Public Sub New(EmailId As Integer, Uid As String)
      Me.EmailId = EmailId
      Me.Uid = Uid
    End Sub
  End Structure

  ''' <summary>
  ''' If anything goes wrong within Pop3MailClient, a Pop3Exception is raised
  ''' </summary>
  Public Class Pop3Exception
    Inherits ApplicationException
    ''' <summary>
    ''' 
    ''' </summary>
    Public Sub New()
    End Sub
    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="ErrorMessage"></param>
    Public Sub New(ByVal ErrorMessage As String)
      MyBase.New(ErrorMessage)
    End Sub
  End Class

  ''' <summary>
  ''' A pop 3 connection goes through the following states:
  ''' </summary>
  Public Enum Pop3ConnectionStateEnum
    ''' <summary>
    ''' undefined
    ''' </summary>
    None = 0
    ''' <summary>
    ''' not connected yet to POP3 server
    ''' </summary>
    Disconnected
    ''' <summary>
    ''' TCP connection has been opened and the POP3 server has sent the greeting. POP3 server expects user name and password
    ''' </summary>
    Authorization
    ''' <summary>
    ''' client has identified itself successfully with the POP3, server has locked all messages 
    ''' </summary>
    Connected
    ''' <summary>
    ''' QUIT command was sent, the server has deleted messages marked for deletion and released the resources
    ''' </summary>
    Closed
  End Enum

  ' Delegates for Pop3MailClient
  ' ============================

  ''' <summary>
  ''' If POP3 Server doesn't react as expected or this code has a problem, but
  ''' can continue with the execution, a Warning is called.
  ''' </summary>
  ''' <param name="WarningText"></param>
  ''' <param name="Response">string received from POP3 server</param>
  Public Delegate Sub WarningHandler(ByVal WarningText As String, ByVal Response As String)

  ''' <summary>
  ''' Traces all the information exchanged between POP3 client and POP3 server plus some
  ''' status messages from POP3 client.
  ''' Helpful to investigate any problem.
  ''' Console.WriteLine() can be used
  ''' </summary>
  ''' <param name="TraceText"></param>
  Public Delegate Sub TraceHandler(ByVal TraceText As String)

  ' cPop3MailClient Class
  ' ====================  

  ''' <summary>
  ''' provides access to emails on a POP3 Server
  ''' </summary>
  Public Class cPop3MailClient

    'Events
    '------

    ''' <summary>
    ''' Called whenever POP3 server doesn't react as expected, but no runtime error is thrown.
    ''' </summary>
    Public Event Warning As WarningHandler

    ''' <summary>
    ''' call warning event
    ''' </summary>
    ''' <param name="methodName">name of the method where warning is needed</param>
    ''' <param name="response">answer from POP3 server causing the warning</param>
    ''' <param name="warningText">explanation what went wrong</param>
    ''' <param name="warningParameters"></param>
    Protected Sub CallWarning(ByVal methodName As String, ByVal response As String, _
     ByVal warningText As String, ByVal ParamArray warningParameters As Object())
      warningText = String.Format(warningText, warningParameters)
      RaiseEvent Warning(Convert.ToString(methodName & Convert.ToString(": ")) & warningText, response)
      CallTrace("!! {0}", warningText)
    End Sub

    ''' <summary>
    ''' Shows the communication between PopClient and PopServer, including warnings
    ''' </summary>
    Public Event Trace As TraceHandler

    ''' <summary>
    ''' call Trace event
    ''' </summary>
    ''' <param name="text">string to be traced</param>
    ''' <param name="parameters"></param>
    Protected Sub CallTrace(ByVal text As String, ByVal ParamArray parameters As Object())
      'RaiseEvent Trace(DateTime.Now.ToString("hh:mm:ss ") + m_popServer + " " + String.Format(text, parameters))
      RaiseEvent Trace(DateTime.Now.ToString + Chr(9) + m_popServer + Chr(9) + String.Format(text, parameters))
    End Sub

    ''' <summary>
    ''' Trace information received from POP3 server
    ''' </summary>
    ''' <param name="text">string to be traced</param>
    ''' <param name="parameters"></param>
    Protected Sub TraceFrom(ByVal text As String, ByVal ParamArray parameters As Object())
      CallTrace("   " + String.Format(text, parameters))
    End Sub

    'Properties
    '------

    ''' <summary>
    ''' Get POP3 server name
    ''' </summary>
    Public ReadOnly Property PopServer() As String
      Get
        Return m_popServer
      End Get
    End Property
    ''' <summary>
    ''' POP3 server name
    ''' </summary>
    Protected m_popServer As String

    ''' <summary>
    ''' Get POP3 server port
    ''' </summary>
    Public ReadOnly Property Port() As Integer
      Get
        Return m_port
      End Get
    End Property
    ''' <summary>
    ''' POP3 server port
    ''' </summary>
    Protected m_port As Integer

    ''' <summary>
    ''' Should SSL be used for connection with POP3 server ?
    ''' </summary>
    Public ReadOnly Property UseSSL() As Boolean
      Get
        Return m_useSSL
      End Get
    End Property
    ''' <summary>
    ''' Should SSL be used for connection with POP3 server ?
    ''' </summary>
    Private m_useSSL As Boolean

    ''' <summary>
    ''' should Pop3MailClient automatically reconnect if POP3 server has dropped the 
    ''' connection due to a timeout ?
    ''' </summary>
    Public Property IsAutoReconnect() As Boolean
      Get
        Return m_isAutoReconnect
      End Get
      Set(ByVal value As Boolean)
        m_isAutoReconnect = value
      End Set
    End Property
    Private m_isAutoReconnect As Boolean = False
    'timeout has occured, we try to perform an autoreconnect
    Private isTimeoutReconnect As Boolean = False

    ''' <summary>
    ''' Get / set read timeout (miliseconds)
    ''' </summary>
    Public Property ReadTimeout() As Integer
      Get
        Return m_readTimeout
      End Get
      Set(ByVal value As Integer)
        m_readTimeout = value
        If pop3Stream IsNot Nothing AndAlso pop3Stream.CanTimeout Then
          pop3Stream.ReadTimeout = m_readTimeout
        End If
      End Set
    End Property
    ''' <summary>
    ''' POP3 server read timeout
    ''' </summary>
    Protected m_readTimeout As Integer = -1

    ''' <summary>
    ''' Get owner name of mailbox on POP3 server
    ''' </summary>
    Public ReadOnly Property Username() As String
      Get
        Return m_username
      End Get
    End Property
    ''' <summary>
    ''' Owner name of mailbox on POP3 server
    ''' </summary>
    Protected m_username As String

    ''' <summary>
    ''' Get password for mailbox on POP3 server
    ''' </summary>
    Public ReadOnly Property Password() As String
      Get
        Return m_password
      End Get
    End Property
    ''' <summary>
    ''' Password for mailbox on POP3 server
    ''' </summary>
    Protected m_password As String

    ''' <summary>
    ''' Get connection status with POP3 server
    ''' </summary>
    Public ReadOnly Property Pop3ConnectionState() As Pop3ConnectionStateEnum
      Get
        Return m_pop3ConnectionState
      End Get
    End Property
    ''' <summary>
    ''' connection status with POP3 server
    ''' </summary>
    Protected m_pop3ConnectionState As Pop3ConnectionStateEnum = Pop3ConnectionStateEnum.Disconnected

    ' Methods
    ' -------

    ''' <summary>
    ''' set POP3 connection state
    ''' </summary>
    ''' <param name="State"></param>
    Protected Sub setPop3ConnectionState(ByVal State As Pop3ConnectionStateEnum)
      m_pop3ConnectionState = State
      CallTrace("   Pop3MailClient Connection State {0} reached", State)
    End Sub

    ''' <summary>
    ''' throw exception if POP3 connection is not in the required state
    ''' </summary>
    ''' <param name="requiredState"></param>
    Protected Sub EnsureState(ByVal requiredState As Pop3ConnectionStateEnum)
      If m_pop3ConnectionState <> requiredState Then
        ' wrong connection state
        Throw New Pop3Exception("GetMailboxStats only accepted during connection state: " + requiredState.ToString() + _
         vbLf & " The connection to server " + m_popServer + " is in state " + m_pop3ConnectionState.ToString())
      End If
    End Sub

    'private fields
    '--------------
    ''' <summary>
    ''' TCP to POP3 server
    ''' </summary>
    Private serverTcpConnection As TcpClient
    ''' <summary>
    ''' Stream from POP3 server with or without SSL
    ''' </summary>
    Private pop3Stream As Stream
    ''' <summary>
    ''' Reader for POP3 message
    ''' </summary>
    Protected pop3StreamReader As StreamReader
    ''' <summary>
    ''' char 'array' for carriage return / line feed
    ''' </summary>
    Protected CRLF As String = vbCr & vbLf

    'public methods
    '--------------

    ''' <summary>
    ''' Make POP3 client ready to connect to POP3 server
    ''' </summary>
    ''' <param name="PopServer"><example>pop.gmail.com</example></param>
    ''' <param name="Port"><example>995</example></param>
    ''' <param name="useSSL">True: SSL is used for connection to POP3 server</param>
    ''' <param name="Username"><example>abc@gmail.com<;/example></param>
    ''' <param name="Password">Secret</param>
    Public Sub New(ByVal PopServer As String, ByVal Port As Integer, ByVal useSSL As Boolean, _
     ByVal Username As String, ByVal Password As String)
      Me.m_popServer = PopServer
      Me.m_port = Port
      Me.m_useSSL = useSSL
      Me.m_username = Username
      Me.m_password = Password
    End Sub

    ''' <summary>
    ''' Connect to POP3 server
    ''' </summary>
    Public Sub Connect()
      If (m_pop3ConnectionState <> Pop3ConnectionStateEnum.Disconnected) AndAlso
       (m_pop3ConnectionState <> Pop3ConnectionStateEnum.Closed) AndAlso
       (Not isTimeoutReconnect) Then
        CallWarning("connect", "", "Connect command received, but connection state is: " + m_pop3ConnectionState.ToString())
      Else
        'establish TCP connection
        Try
          CallTrace("   Connect at port {0}", m_port)
          serverTcpConnection = New TcpClient(m_popServer, m_port)
        Catch ex As Exception
          Throw New Pop3Exception("Connection to server " + m_popServer + ", port " + m_port.ToString + " failed." & vbLf & "Runtime Error: " + ex.ToString())
        End Try

        If m_useSSL Then
          'get SSL stream
          Try
            CallTrace("   Get SSL connection")
            pop3Stream = New SslStream(serverTcpConnection.GetStream(), False)
            pop3Stream.ReadTimeout = m_readTimeout
          Catch ex As Exception
            Throw New Pop3Exception("Server " + m_popServer + " found, but cannot get SSL data stream." & vbLf & "Runtime Error: " + ex.ToString())
          End Try

          'perform SSL authentication
          Try
            CallTrace("   Get SSL authentication")
            DirectCast(pop3Stream, SslStream).AuthenticateAsClient(m_popServer)
          Catch ex As Exception
            Throw New Pop3Exception("Server " + m_popServer + " found, but problem with SSL Authentication." & vbLf & "Runtime Error: " + ex.ToString())
          End Try
        Else
          'create a stream to POP3 server without using SSL
          Try
            CallTrace("   Get connection without SSL")
            pop3Stream = serverTcpConnection.GetStream()
            pop3Stream.ReadTimeout = m_readTimeout
          Catch ex As Exception
            Throw New Pop3Exception("Server " + m_popServer + " found, but cannot get data stream (without SSL)." & vbLf & "Runtime Error: " + ex.ToString())
          End Try
        End If

        'get stream for reading from pop server
        'POP3 allows only US-ASCII. The message will be translated in the proper encoding in a later step
        Try
          pop3StreamReader = New StreamReader(pop3Stream, Encoding.ASCII)
        Catch ex As Exception
          If m_useSSL Then
            Throw New Pop3Exception("Server " + m_popServer + " found, but cannot read from SSL stream." & vbLf & "Runtime Error: " + ex.ToString())
          Else
            Throw New Pop3Exception("Server " + m_popServer + " found, but cannot read from stream (without SSL)." & vbLf & "Runtime Error: " + ex.ToString())
          End If
        End Try

        'ready for authorisation
        Dim response As String = ""
        If Not readSingleLine(response) Then
          Throw New Pop3Exception(Convert.ToString("Server " + m_popServer + " not ready to start AUTHORIZATION." & vbLf & "Message: ") & response)
        End If
        setPop3ConnectionState(Pop3ConnectionStateEnum.Authorization)

        'send user name
        If Not executeCommand("USER " + m_username, response) Then
          Throw New Pop3Exception(Convert.ToString("Server " + m_popServer + " doesn't accept username '" + m_username + "'." & vbLf & "Message: ") & response)
        End If

        'send password
        If Not executeCommand("PASS " + m_password, response) Then
          Throw New Pop3Exception(Convert.ToString("Server " + m_popServer + " doesn't accept password '" + m_password + "' for user '" + m_username + "'." & vbLf & "Message: ") & response)
        End If

        setPop3ConnectionState(Pop3ConnectionStateEnum.Connected)
      End If
    End Sub

    ''' <summary>
    ''' Disconnect from POP3 Server
    ''' </summary>
    Public Sub Disconnect()
      If m_pop3ConnectionState = Pop3ConnectionStateEnum.Disconnected OrElse _
       m_pop3ConnectionState = Pop3ConnectionStateEnum.Closed Then
        CallWarning("disconnect", "", "Disconnect received, but was already disconnected.")
      Else
        'ask server to end session and possibly to remove emails marked for deletion
        Try
          Dim response As String = ""
          If executeCommand("QUIT", response) Then
            'server says everything is ok
            setPop3ConnectionState(Pop3ConnectionStateEnum.Closed)
          Else
            'server says there is a problem
            CallWarning("Disconnect", response, Convert.ToString("negative response from server while closing connection: ") & response)
            setPop3ConnectionState(Pop3ConnectionStateEnum.Disconnected)
          End If
        Finally
          'close connection
          If pop3Stream IsNot Nothing Then
            pop3Stream.Close()
          End If

          pop3StreamReader.Close()
        End Try
      End If
    End Sub

    ''' <summary>
    ''' Delete message from server.
    ''' The POP3 server marks the message as deleted.  Any future
    ''' reference to the message-number associated with the message
    ''' in a POP3 command generates an error.  The POP3 server does
    ''' not actually delete the message until the POP3 session
    ''' enters the UPDATE state.
    ''' </summary>
    ''' <param name="msg_number"></param>
    ''' <returns></returns>
    Public Function DeleteEmail(ByVal msg_number As Integer) As Boolean
      EnsureState(Pop3ConnectionStateEnum.Connected)
      Dim response As String = ""
      If Not executeCommand("DELE " + msg_number.ToString(), response) Then
        CallWarning("DeleteEmail", response, "negative response for email (Id: {0}) delete request", msg_number)
        Return False
      End If
      Return True
    End Function

    ''' <summary>
    ''' Get a list of all Email IDs available in mailbox
    ''' </summary>
    ''' <returns></returns>
    Public Function GetEmailIdList(ByRef EmailIds As List(Of Integer)) As Boolean
      EnsureState(Pop3ConnectionStateEnum.Connected)
      EmailIds = New List(Of Integer)()

      'get server response status line
      Dim response As String = ""
      If Not executeCommand("LIST", response) Then
        CallWarning("GetEmailIdList", response, "negative response for email list request")
        Return False
      End If

      'get every email id
      Dim EmailId As Integer
      While readMultiLine(response)
        If Integer.TryParse(response.Split(" "c)(0), EmailId) Then
          EmailIds.Add(EmailId)
        Else
          CallWarning("GetEmailIdList", response, "first characters should be integer (EmailId)")
        End If
      End While
      TraceFrom("{0} email ids received", EmailIds.Count)
      Return True
    End Function

    ''' <summary>
    ''' get size of one particular email
    ''' </summary>
    ''' <param name="msg_number"></param>
    ''' <returns></returns>
    Public Function GetEmailSize(ByVal msg_number As Integer) As Integer
      EnsureState(Pop3ConnectionStateEnum.Connected)
      Dim response As String = ""
      executeCommand("LIST " + msg_number.ToString(), response)
      Dim EmailSize As Integer = 0
      Dim responseSplit As String() = response.Split(" "c)
      If responseSplit.Length < 2 OrElse Not Integer.TryParse(responseSplit(2), EmailSize) Then
        CallWarning("GetEmailSize", response, "'+OK int int' format expected (EmailId, EmailSize)")
      End If

      Return EmailSize
    End Function

    ''' <summary>
    ''' Get a list with the unique IDs of all Email available in mailbox.
    ''' 
    ''' Explanation:
    ''' EmailIds for the same email can change between sessions, whereas the unique Email id
    ''' never changes for an email.
    ''' </summary>
    ''' <param name="EmailIds"></param>
    ''' <returns></returns>
    Public Function GetUniqueEmailIdList(ByRef EmailIds As List(Of EmailUid)) As Boolean
      EnsureState(Pop3ConnectionStateEnum.Connected)
      EmailIds = New List(Of EmailUid)()

      'get server response status line
      Dim response As String = ""
      If Not executeCommand("UIDL ", response) Then
        CallWarning("GetUniqueEmailIdList", response, "negative response for email list request")
        Return False
      End If

      'get every email unique id
      Dim EmailId As Integer
      While readMultiLine(response)
        Dim responseSplit As String() = response.Split(" "c)
        If responseSplit.Length < 2 Then
          CallWarning("GetUniqueEmailIdList", response, "response not in format 'int string'")
        ElseIf Not Integer.TryParse(responseSplit(0), EmailId) Then
          CallWarning("GetUniqueEmailIdList", response, "first charaters should be integer (Unique EmailId)")
        Else
          EmailIds.Add(New EmailUid(EmailId, responseSplit(1)))
        End If
      End While
      TraceFrom("{0} unique email ids received", EmailIds.Count)
      Return True
    End Function

    ''' <summary>
    ''' get a list with all currently available messages and the UIDs
    ''' </summary>
    ''' <param name="EmailIds">EmailId Uid list</param>
    ''' <returns>false: server sent negative response (didn't send list)</returns>
    Public Function GetUniqueEmailIdList(ByRef EmailIds As SortedList(Of String, Integer)) As Boolean
      EnsureState(Pop3ConnectionStateEnum.Connected)
      EmailIds = New SortedList(Of String, Integer)()

      'get server response status line
      Dim response As String = ""
      If Not executeCommand("UIDL", response) Then
        CallWarning("GetUniqueEmailIdList", response, "negative response for email list request")
        Return False
      End If

      'get every email unique id
      Dim EmailId As Integer
      While readMultiLine(response)
        Dim responseSplit As String() = response.Split(" "c)
        If responseSplit.Length < 2 Then
          CallWarning("GetUniqueEmailIdList", response, "response not in format 'int string'")
        ElseIf Not Integer.TryParse(responseSplit(0), EmailId) Then
          CallWarning("GetUniqueEmailIdList", response, "first charaters should be integer (Unique EmailId)")
        Else
          EmailIds.Add(responseSplit(1), EmailId)
        End If
      End While
      TraceFrom("{0} unique email ids received", EmailIds.Count)
      Return True
    End Function

    ''' <summary>
    ''' get size of one particular email
    ''' </summary>
    ''' <param name="msg_number"></param>
    ''' <returns></returns>
    Public Function GetUniqueEmailId(ByVal msg_number As EmailUid) As Integer
      EnsureState(Pop3ConnectionStateEnum.Connected)
      Dim response As String = ""
      executeCommand("LIST " + msg_number.ToString(), response)
      Dim EmailSize As Integer = 0
      Dim responseSplit As String() = response.Split(" "c)
      If responseSplit.Length < 2 OrElse Not Integer.TryParse(responseSplit(2), EmailSize) Then
        CallWarning("GetEmailSize", response, "'+OK int int' format expected (EmailId, EmailSize)")
      End If

      Return EmailSize
    End Function

    ''' <summary>
    ''' Sends an 'empty' command to the POP3 server. Server has to respond with +OK
    ''' </summary>
    ''' <returns>true: server responds as expected</returns>
    Public Function NOOP() As Boolean
      EnsureState(Pop3ConnectionStateEnum.Connected)
      Dim response As String = ""
      If Not executeCommand("NOOP", response) Then
        CallWarning("NOOP", response, "negative response for NOOP request")
        Return False
      End If
      Return True
    End Function

    ''' <summary>
    ''' Should the raw content, the US-ASCII code as received, be traced
    ''' GetRawEmail will switch it on when it starts and off once finished
    ''' 
    ''' Inheritors might use it to get the raw email
    ''' </summary>
    Protected isTraceRawEmail As Boolean = False


    ''' <summary>
    ''' contains one MIME part of the email in US-ASCII, needs to be translated in .NET string (Unicode)
    ''' contains the complete email in US-ASCII, needs to be translated in .NET string (Unicode)
    ''' For speed reasons, reuse StringBuilder
    ''' </summary>
    Protected RawEmailSB As StringBuilder

    ''' <summary>
    ''' Reads the complete text of a message
    ''' </summary>
    ''' <param name="MessageNo">Email to retrieve</param>
    ''' <param name="EmailText">ASCII string of complete message</param>
    ''' <returns></returns>
    Public Function GetRawEmail(ByVal MessageNo As Integer, ByRef EmailText As String) As Boolean
      'send 'RETR int' command to server
      If Not SendRetrCommand(MessageNo) Then
        EmailText = Nothing
        Return False
      End If

      'get the lines
      Dim response As String = ""
      Dim LineCounter As Integer = 0
      'empty StringBuilder
      If RawEmailSB Is Nothing Then
        RawEmailSB = New StringBuilder(100000)
      Else
        RawEmailSB.Length = 0
      End If
      isTraceRawEmail = True
      While readMultiLine(response)
        LineCounter += 1
      End While
      EmailText = RawEmailSB.ToString()
      TraceFrom("email with {0} lines,  {1} chars received", LineCounter.ToString(), EmailText.Length)
      Return True
    End Function

    ' ''' <summary>
    ' ''' Requests from POP3 server a specific email and returns a stream with the message content (header and body)
    ' ''' </summary>
    ' ''' <param name="MessageNo"></param>
    ' ''' <param name="EmailStreamReader"></param>
    ' ''' <returns>false: POP3 server cannot provide this message</returns>
    'Public Function GetEmailStream(ByVal MessageNo As Integer, ByRef EmailStreamReader As StreamReader) As Boolean
    '  'send 'RETR int' command to server
    '  If Not SendRetrCommand(MessageNo) Then
    '    EmailStreamReader = Nothing
    '    Return False
    '  End If
    '  EmailStreamReader = sslStreamReader
    '  Return True
    'End Function

    ''' <summary>
    ''' Unmark any emails from deletion. The server only deletes email really
    ''' once the connection is properly closed.
    ''' </summary>
    ''' <returns>true: emails are unmarked from deletion</returns>
    Public Function UndeleteAllEmails() As Boolean
      EnsureState(Pop3ConnectionStateEnum.Connected)
      Dim response As String = ""
      Return executeCommand("RSET", response)
    End Function

    ''' <summary>
    ''' Get mailbox statistics
    ''' </summary>
    ''' <param name="NumberOfMails"></param>
    ''' <param name="MailboxSize"></param>
    ''' <returns></returns>
    Public Function GetMailboxStats(ByRef NumberOfMails As Integer, ByRef MailboxSize As Integer) As Boolean
      EnsureState(Pop3ConnectionStateEnum.Connected)

      'interpret response
      Dim response As String = ""
      NumberOfMails = 0
      MailboxSize = 0
      If executeCommand("STAT", response) Then
        'got a positive response
        Dim responseParts As String() = response.Split(" "c)
        If responseParts.Length < 2 Then
          'response format wrong
          Throw New Pop3Exception(Convert.ToString("Server " + m_popServer + " sends illegally formatted response." + _
           vbLf & "Expected format: +OK int int" + _
           vbLf & "Received response: ") & response)
        End If
        NumberOfMails = Integer.Parse(responseParts(1))
        MailboxSize = Integer.Parse(responseParts(2))
        Return True
      End If
      Return False
    End Function

    ''' <summary>
    ''' Send RETR command to POP 3 server to fetch one particular message
    ''' </summary>
    ''' <param name="MessageNo">ID of message required</param>
    ''' <returns>false: negative server respond, message not delivered</returns>
    Protected Function SendRetrCommand(ByVal MessageNo As Integer) As Boolean
      EnsureState(Pop3ConnectionStateEnum.Connected)
      ' retrieve mail with message number
      Dim response As String = ""
      If Not executeCommand("RETR " + MessageNo.ToString(), response) Then
        CallWarning("GetRawEmail", response, "negative response for email (ID: {0}) request", MessageNo)
        Return False
      End If
      Return True
    End Function

    'Helper methodes
    '---------------

    Public isDebug As Boolean = False

    ''' <summary>
    ''' sends the 4 letter command to POP3 server (adds CRLF) and waits for the
    ''' response of the server
    ''' </summary>
    ''' <param name="command">command to be sent to server</param>
    ''' <param name="response">answer from server</param>
    ''' <returns>false: server sent negative acknowledge, i.e. server could not execute command</returns>
    Private Function executeCommand(ByVal command As String, ByRef response As String) As Boolean
      'send command to server
      Dim commandBytes As Byte() = System.Text.Encoding.ASCII.GetBytes((command & CRLF).ToCharArray())
      CallTrace("Tx '{0}'", command)
      Dim isSupressThrow As Boolean = False
      Try
        pop3Stream.Write(commandBytes, 0, commandBytes.Length)
        If isDebug Then
          isDebug = False
          Throw New IOException("Test", New SocketException(10053))
        End If
      Catch ex As IOException
        'Unable to write data to the transport connection. Check if reconnection should be tried
        isSupressThrow = executeReconnect(ex, command, commandBytes)
        If Not isSupressThrow Then
          Throw
        End If
      End Try
      pop3Stream.Flush()

      'read response from server
      response = Nothing
      Try
        response = pop3StreamReader.ReadLine()
      Catch ex As IOException
        'Unable to write data to the transport connection. Check if reconnection should be tried
        isSupressThrow = executeReconnect(ex, command, commandBytes)
        If isSupressThrow Then
          'wait for response one more time
          response = pop3StreamReader.ReadLine()
        Else
          Throw
        End If
      End Try
      If response Is Nothing Then
        Throw New Pop3Exception("Server " + m_popServer + " has not responded, timeout has occured.")
      End If
      CallTrace("Rx '{0}'", response)
      Return (response.Length > 0 AndAlso response(0) = "+"c)
    End Function

    ''' <summary>
    ''' reconnect, if there is a timeout exception and isAutoReconnect is true
    ''' 
    ''' </summary>
    Private Function executeReconnect(ByVal ex As IOException, ByVal command As String, _
     ByVal commandBytes As Byte()) As Boolean
      If ex.InnerException IsNot Nothing AndAlso TypeOf ex.InnerException Is SocketException Then
        'SocketException
        Dim innerEx As SocketException = DirectCast(ex.InnerException, SocketException)
        If innerEx.ErrorCode = 10053 Then
          'probably timeout: An established connection was aborted by the software in your host machine.
          CallWarning("ExecuteCommand", "", "probably timeout occured")
          If m_isAutoReconnect Then
            'try to reconnect and send one more time
            isTimeoutReconnect = True
            Try
              CallTrace("   try to auto reconnect")
              Connect()

              CallTrace("   reconnect successful, try to resend command")
              CallTrace("Tx '{0}'", command)
              pop3Stream.Write(commandBytes, 0, commandBytes.Length)
              pop3Stream.Flush()
              Return True
            Finally
              isTimeoutReconnect = False
            End Try

          End If
        End If
      End If
      Return False
    End Function

    ' ''' <summary>
    ' ''' sends the 4 letter command to POP3 server (adds CRLF)
    ' ''' </summary>
    ' ''' <param name="command"></param>
    'Protected Sub SendCommand(ByVal command As String)
    '  Dim commandBytes As Byte() = System.Text.Encoding.ASCII.GetBytes((command & CRLF).ToCharArray())
    '  CallTrace("Tx '{0}'", command)
    '  Try
    '    pop3Stream.Write(commandBytes, 0, commandBytes.Length)
    '  Catch ex As IOException
    '    'Unable to write data to the transport connection:
    '    If ex.InnerException IsNot Nothing AndAlso TypeOf ex.InnerException Is SocketException Then
    '      'SocketException
    '      Dim innerEx As SocketException = DirectCast(ex.InnerException, SocketException)
    '      If innerEx.ErrorCode = 10053 Then
    '        'probably timeout: An established connection was aborted by the software in your host machine.
    '        CallWarning("SendCommand", "", "probably timeout occured")
    '        If m_isAutoReconnect Then
    '          'try to reconnect and send one more time
    '          isTimeoutReconnect = True
    '          Try
    '            CallTrace("   try to auto reconnect")
    '            Connect()

    '            CallTrace("   reconnect successful, try to resend command")
    '            CallTrace("Tx '{0}'", command)
    '            pop3Stream.Write(commandBytes, 0, commandBytes.Length)
    '          Finally
    '            isTimeoutReconnect = False
    '          End Try
    '          Return
    '        End If
    '      End If
    '    End If
    '    Throw
    '  End Try
    '  pop3Stream.Flush()
    'End Sub

    ''' <summary>
    ''' read single line response from POP3 server. 
    ''' <example>Example server response: +OK asdfkjahsf</example>
    ''' </summary>
    ''' <param name="response">response from POP3 server</param>
    ''' <returns>true: positive response</returns>
    Protected Function readSingleLine(ByRef response As String) As Boolean
      response = Nothing
      Try
        response = pop3StreamReader.ReadLine()
      Catch ex As Exception
        Dim s As String = ex.Message
      End Try
      If response Is Nothing Then
        Throw New Pop3Exception("Server " + m_popServer + " has not responded, timeout has occured.")
      End If
      CallTrace("Rx '{0}'", response)
      Return (response.Length > 0 AndAlso response(0) = "+"c)
    End Function

    ''' <summary>
    ''' read one line in multiline mode from the POP3 server. 
    ''' </summary>
    ''' <param name="response">line received</param>
    ''' <returns>false: end of message</returns>
    Protected Function readMultiLine(ByRef response As String) As Boolean
      response = Nothing
      response = pop3StreamReader.ReadLine()
      If response Is Nothing Then
        Throw New Pop3Exception("Server " + m_popServer + " has not responded, probably timeout has occured.")
      End If
      If isTraceRawEmail Then
        'collect all responses as received
        RawEmailSB.Append(response & CRLF)
      End If
      'check for byte stuffing, i.e. if a line starts with a '.', another '.' is added, unless
      'it is the last line
      If response.Length > 0 AndAlso response(0) = "."c Then
        If response = "." Then
          'closing line found
          Return False
        End If
        'remove the first '.'
        response = response.Substring(1, response.Length - 1)
      End If
      Return True
    End Function

  End Class

End Namespace


то мне его просто надо переделать в IMAP? Насколько тяжело?

Ну, вот POP3 дебаг(скачиваем единственное письмо, с удалением на сервере)

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
19.05.2015 16:41:23	pop.gmail.com	   Connect at port 995
19.05.2015 16:41:23	pop.gmail.com	   Get SSL connection
19.05.2015 16:41:23	pop.gmail.com	   Get SSL authentication
19.05.2015 16:41:23	pop.gmail.com	Rx '+OK Gpop ready for requests from 176.17.213.145 c128mb48153737lfb'
19.05.2015 16:41:23	pop.gmail.com	   Pop3MailClient Connection State Authorization reached
19.05.2015 16:41:23	pop.gmail.com	Tx 'USER username@gmail.com'
19.05.2015 16:41:23	pop.gmail.com	Rx '+OK send PASS'
19.05.2015 16:41:23	pop.gmail.com	Tx 'PASS password'
19.05.2015 16:41:25	pop.gmail.com	Rx '+OK Welcome.'
19.05.2015 16:41:25	pop.gmail.com	   Pop3MailClient Connection State Connected reached
19.05.2015 16:41:25	pop.gmail.com	Tx 'STAT'
19.05.2015 16:41:25	pop.gmail.com	Rx '+OK 1 564222'
19.05.2015 16:41:25	pop.gmail.com	Tx 'LIST 1'
19.05.2015 16:41:25	pop.gmail.com	Rx '+OK 1 564222'
19.05.2015 16:41:25	pop.gmail.com	Tx 'RETR 1'
19.05.2015 16:41:25	pop.gmail.com	Rx '+OK message follows'
19.05.2015 16:41:26	pop.gmail.com	   email with 7284 lines,  564225 chars received
19.05.2015 16:41:26	pop.gmail.com	Tx 'DELE 1'
19.05.2015 16:41:27	pop.gmail.com	Rx '+OK marked for deletion'
19.05.2015 16:41:27	pop.gmail.com	Tx 'QUIT'
19.05.2015 16:41:27	pop.gmail.com	Rx '+OK Farewell.'
19.05.2015 16:41:27	pop.gmail.com	   Pop3MailClient Connection State Closed reached



Всего 7 команд - выделил (LIST здесь даже лишняя).

А никто мне в столбик не напишет такие же команды для IMAP (такой же алгоритм)?
Чтоб по спецификациям не плавать?

До кучи еще бы аналог:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
19.05.2015 16:50:51	pop.gmail.com	Tx 'LIST'
19.05.2015 16:50:51	pop.gmail.com	Rx '+OK 0 messages (0 bytes)'
19.05.2015 16:50:51	pop.gmail.com	   0 email ids received
19.05.2015 16:50:51	pop.gmail.com	Tx 'UIDL '
19.05.2015 16:50:51	pop.gmail.com	Rx '+OK'
19.05.2015 16:50:51	pop.gmail.com	   0 unique email ids received
19.05.2015 16:50:51	pop.gmail.com	Tx 'NOOP'
19.05.2015 16:50:51	pop.gmail.com	Rx '+OK'
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963024
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Чтоб по спецификациям не плавать?
по ним не плавать нужно, а знать - https://tools.ietf.org/html/rfc3501

не хочешь углубляться - бери готовую библиотеку
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963063
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изопропил https://tools.ietf.org/html/rfc3501
За ссылку спасибо.

Если знаешь, м.б. выпишешь мне 7 команд в столбик. А я попробую углубиться именно в те которые мне нужны а не в 100 страниц сухих доков и воткнуть их в POP3 шаблон.

>бери готовую библиотеку
не возьму
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963135
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77 то мне его просто надо переделать в IMAP? Насколько тяжело?в общем да и не тяжелее, чем pop3

Дмитрий77 А никто мне в столбик не напишет такие же команды для IMAP (такой же алгоритм)?
A1 LOGIN логин пароль
A2 SELECT INBOX
A3 SEARCH UNSEEN
тут возвращается массив значений, идентифицирующих непрочитанные письма.
A4 FETCH значение (тут возможны еще какие-то параметры типа body[header], FLAGS, смысл которых я не помню, смотри спецификацию)
а с удалением непонятки. как таковой команды удаления нет, есть возня с флагами - STORE значение +FLAGS \Deleted,
копирование в мусорку - COPY значение Trash и очищение выбранной папки от писем с флагом Deleted - EXPUNGE.
A5 LOGOUT

фишка IMAP - нужно вести сквозную нумерацию отсылаемых команд (A1-A5)

до конца я его так и ниасилил. тренировался на mail.ru, а там был то ли баг, то ли фича: команда, имеющая параметром значение , применялась к двум сообщениям, заданному и следующему. а если сообщение одно или последнее, то все ок. мэйлру вопрос о том, что за ерунда творится, проигнорировало. по факту IMAP мне не был нужен, я и забил на него совсем.
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963151
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
я так и не помню, получилось у меня удалить или нет.

Дмитрий77 До кучи еще бы аналог:что такое LIST не помню, UIDL не знаю, а NOOP точно такой же: Axxx NOOP
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963155
carrotik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Изопропил https://tools.ietf.org/html/rfc3501
За ссылку спасибо.

Если знаешь, м.б. выпишешь мне 7 команд в столбик. А я попробую углубиться именно в те которые мне нужны а не в 100 страниц сухих доков и воткнуть их в POP3 шаблон.

>бери готовую библиотеку
не возьму

,. да наберите в гугле imap commands, там все просто (главное, не забыть тэги перед командой ставить, хоть точку, хоть а1)
например
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963164
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
carrotik(главное, не забыть тэги перед командой ставить, хоть точку, хоть а1)хм, а в доке, что я читал, речь была конкретно про нумерацию.
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963169
carrotik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Antonariy,

... у меня удаление примерно вот так работает

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
Protected Sub SendCommands(ByVal strCommand As String)
        If Not netStream.CanWrite Then
            ConnectToServer()
        End If
        Dim sendBytes As [Byte]() = Encoding.ASCII.GetBytes(".. " & strCommand & vbCrLf)
        netStream.Write(sendBytes, 0, sendBytes.Length)
    End Sub

Protected Sub DeleteMessage()
        Dim strID As String = String.Empty
        For Each row As GridViewRow In MyDataGrid.Rows
            Dim cb As CheckBox = row.FindControl("chkMess")
            If cb IsNot Nothing AndAlso cb.Checked Then
                strID += MyDataGrid.DataKeys(row.RowIndex).Value + ","
            End If
        Next
        SendCommands("select " & Chr(34) & LinksTreeView.SelectedNode.Value & Chr(34))
        ReadResponse()
        SendCommands("store " + strID.TrimEnd(",") + " +flags.silent (\Deleted)")
        ReadResponse()
        SendCommands("expunge")
        ReadResponse()
        ShowGrid()
    End Sub
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963173
carrotik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Antonariycarrotik(главное, не забыть тэги перед командой ставить, хоть точку, хоть а1)хм, а в доке, что я читал, речь была конкретно про нумерацию.

...я вот две точки ставлю ...
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963177
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77>бери готовую библиотеку
не возьму
а деньги считал?
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963202
carrotik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
carrotikAntonariyпропущено...
хм, а в доке, что я читал, речь была конкретно про нумерацию.

...я вот две точки ставлю ...

.. кстати, я тренировался и написал рабочее приложение только для корпоративного мейл-сервера (там postfix и courier-IMAP) ... возможно на публичных другие требования ....
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963204
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ИзопропилДмитрий77>бери готовую библиотеку
не возьму
а деньги считал?
А че деньги? Деньги капают потихоньку.
У меня творческий процесс написания проги никак не связан с техническим процессом собирания денег (за предыдущие версии).
Если так рассуждать, то я уже полгода работаю "бесплатно" (переписывая проект на .Net).
Я работаю на перспективу.

Ребята вроде дело подсказывают, будем экспериментировать.

Просто я на POP3+SSL отвел себе неделю, а сделал за пару дней (уже почти все довставлял в проект, довожу тесты).
Если делать IMAP, то лучше делать сразу, чтоб потом все не вспоминать по новой.
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963218
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Если делать IMAP, то лучше делать сразу, чтоб потом все не вспоминать по новой.
если есть время(которое деньги) -то конечно,
есть маленькое но - кривых IMAP4 серверов куда больше чем кривых POP3
так что готовься фиксить чужие баги
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963439
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
carrotik.. посмотрите MailSystem.NET, если хотите использовать готовую библиотеку ...
Скачал,Посмотрел. Много там всего.
Смотреть так понимаю надо прежде всего Imap4Client.cs ?
Если под готовой понимается запечатанное (да пусть даже и открытое) нечто размером этак 15MB, предполагающее использовать всю OpenSource-ную классику типа OpenSLL и еще штук 10 впридачу, то нет конечно.
Если нечто, из чего можно выдрать код хоть как-то поддающийся пониманию (пусть 1000 строк, пусть даже 3000), то это меня устраивает.

Чем хорош был приведенный пример pop3, 17662816 (под спойлером), что это именно законченный класс почти без лишних прибамбасов.
Я было пытался его начать переписывать под IMAP, но блин по-другому там все, парсинги команд-ответов для POP3 не годятся для IMAP, а высасывать их из пальца желания нет. Авторизоваться удалось, а даже грамотно обработать OK/Исключение после авторизации - ни фига.


Так что лучше взять с нуля готовое что-то другое.
Вот удастся ли выдрать каноничный класс из MailSystem.NET - пока не знаю (т.е. насколько автор пользуется всеми многочисленными кодами, что у него там есть).
Ну и плюс от самого Imap мне надо самый минимум, ползать по всем папкам мне не надо.

Попробую методом выдирания и тестирования кусков кода.
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963473
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне кажется, что на IMAP правильно будет забить.
Пытался выдирать код из MailSystem.NET -не завелось, за несколько часов даже коннекта сделать не сумел.
Скачал еще несколько поделок - либо заумные, либо глючные, либо слишком упрощенные - типа без SSL(ну это ладно знаю как прикрутить), либо вообще без парсинга ответов, логов и обработки ошибок, типа читайте в консоли.

И самое главное, укрепилось подозрение в том что (конкретно на gmail) через imap в принципе нельзя удалить письмо чтоб его потом нельзя было скачать по pop3.
Ситуация примерно соответствует сказанному здесь 3-мя людьми, ну и разным отзывам на других форумах.

Короче фигня это, хватит того что POP3+SSL осилил.
С IMAP я за 2-3 дня не справлюсь, а больше - действительно времени жалко.
И по большому счету смысл IMAP не очень подходит под мою задачу (чтоб шарить один почтовый ящик -да, чтоб штатно выкачивать - думаю нет). Я им честно говоря за 15 лет никогда сам и не пользовался.
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963689
carrotik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Мне кажется, что на IMAP правильно будет забить.
Пытался выдирать код из MailSystem.NET -не завелось, за несколько часов даже коннекта сделать не сумел.
Скачал еще несколько поделок - либо заумные, либо глючные, либо слишком упрощенные - типа без SSL(ну это ладно знаю как прикрутить), либо вообще без парсинга ответов, логов и обработки ошибок, типа читайте в консоли.

И самое главное, укрепилось подозрение в том что (конкретно на gmail) через imap в принципе нельзя удалить письмо чтоб его потом нельзя было скачать по pop3.
Ситуация примерно соответствует сказанному здесь 3-мя людьми, ну и разным отзывам на других форумах.

Короче фигня это, хватит того что POP3+SSL осилил.
С IMAP я за 2-3 дня не справлюсь, а больше - действительно времени жалко.
И по большому счету смысл IMAP не очень подходит под мою задачу (чтоб шарить один почтовый ящик -да, чтоб штатно выкачивать - думаю нет). Я им честно говоря за 15 лет никогда сам и не пользовался.

.. если вы хотите выкачивать сообщения полностью (с аттачментами), то РОР3 как раз под это и заточен .. IMAP я использую для веб-майлового приложения, чтобы можно было вытащить заголовки в грид, а прикрепленные файлы выкачивать уже по мере необходимости ... там есть команда fetch bodystructure, которая выдает структуру письма с номерами частей, соответственно, можно обращаться к каждой части письма (телу, прикрепленным файлам) отдельно .. если все равно тащить все письмо, то ИМАП тут только все усложняет ...
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963808
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
carrotik чтобы можно было вытащить заголовки в гридpop3 тоже позволяет вытаскивать лишь заголовки.
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963811
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
команда TOP
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963926
carrotik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Antonariy,

..да, но там парсить еще надо первые строки на предмет поиска заголовков .. в IMAP-e каждый заголовок можно вытащить командой
fetch body[header.fields(subject)], например, потом там есть search по дате (периоду - since/before) сообщения ... в общем, для веб-майла мне было удобнее IMAP пользовать .. но это дело вкуса ...
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963958
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
имхо использовать протоколы IMAP, POP, SMTP это вообще плохая идея,эти протоколы древние как говно мамонта.
безопасность этих протокол отдыхает
А писать свой pop3, imap клиент, это написание велосипеда, все же давно уже по 100500 раз написано
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38963971
carrotik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman Mejtesимхо использовать протоколы IMAP, POP, SMTP это вообще плохая идея,эти протоколы древние как говно мамонта.
безопасность этих протокол отдыхает
А писать свой pop3, imap клиент, это написание велосипеда, все же давно уже по 100500 раз написано

...да ... но когда возникают вопросы пользователей "Я хочу видеть это вот так", то править 100500 раз написанного чужого клиента вызывает больше раздражения, нежели написать свой ...
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38964110
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman Mejtesимхо использовать протоколы IMAP, POP, SMTP это вообще плохая идея,эти протоколы древние как говно мамонта.ага, попроси мир больше никогда не пользоваться электронной почтой.

Roman Mejtesбезопасность этих протокол отдыхаетих безопасность обеспечивает тот же механизм, что обеспечивает безопасность https, нужно только его задействовать, поставив где надо галочки. или на https у тебя тоже зуб есть?

Roman MejtesА писать свой pop3, imap клиент, это написание велосипеда, все же давно уже по 100500 раз написано никто и не пишет с нуля, обычно из готового велосипеда выдирают раму, а колеса прикручивают куда требуется.
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38964185
Roman Mejtes
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AntonariyRoman Mejtesимхо использовать протоколы IMAP, POP, SMTP это вообще плохая идея,эти протоколы древние как говно мамонта.ага, попроси мир больше никогда не пользоваться электронной почтой.
я сам удивляюсь тому, что в эпоху мгновенной передачи цифровых сообщений этим говном до сих пор все пользуются =)
могли бы уже что то новое придумать :)
Roman MejtesА писать свой pop3, imap клиент, это написание велосипеда, все же давно уже по 100500 раз написано никто и не пишет с нуля, обычно из готового велосипеда выдирают раму, а колеса прикручивают куда требуется.
дык автор то, судя по теме свой пилит, через сокеты цепляется и фигачит.. Дело хозяйское конечно, если надо , пусть страдает :)
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38964207
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Roman Mejtesдык автор то, судя по теме свой пилит, через сокеты цепляется и фигачит.. Дело хозяйское конечно, если надо , пусть страдает :)ну, автор и колеса разобрал :)
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38964365
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я могу сказать, на чем я принципиально споткнулся пытаясь переделать POP3 в IMAP:
Дмитрий77Antonariy,
я так понимаю из твоего кода и твоих комментариев, что принцип общения с POP3 и IMAP абсолютно одинаков:
команда ->
<- ответ
анализ ответа
При необходимости оборачиваем в SSL-stream (вот здесь чувствуются преимущества .Net).
Так?

Т.е. получается что если класс для POP3 я передрал/написал (ага, 1009 строк):

Код: vbnet
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.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
506.
507.
508.
509.
510.
511.
512.
513.
514.
515.
516.
517.
518.
519.
520.
521.
522.
523.
524.
525.
526.
527.
528.
529.
530.
531.
532.
533.
534.
535.
536.
537.
538.
539.
540.
541.
542.
543.
544.
545.
546.
547.
548.
549.
550.
551.
552.
553.
554.
555.
556.
557.
558.
559.
560.
561.
562.
563.
564.
565.
566.
567.
568.
569.
570.
571.
572.
573.
574.
575.
576.
577.
578.
579.
580.
581.
582.
583.
584.
585.
586.
587.
588.
589.
590.
591.
592.
593.
594.
595.
596.
597.
598.
599.
600.
601.
602.
603.
604.
605.
606.
607.
608.
609.
610.
611.
612.
613.
614.
615.
616.
617.
618.
619.
620.
621.
622.
623.
624.
625.
626.
627.
628.
629.
630.
631.
632.
633.
634.
635.
636.
637.
638.
639.
640.
641.
642.
643.
644.
645.
646.
647.
648.
649.
650.
651.
652.
653.
654.
655.
656.
657.
658.
659.
660.
661.
662.
663.
664.
665.
666.
667.
668.
669.
670.
671.
672.
673.
674.
675.
676.
677.
678.
679.
680.
681.
682.
683.
684.
685.
686.
687.
688.
689.
690.
691.
692.
693.
694.
695.
696.
697.
698.
699.
700.
701.
702.
703.
704.
705.
706.
707.
708.
709.
710.
711.
712.
713.
714.
715.
716.
717.
718.
719.
720.
721.
722.
723.
724.
725.
726.
727.
728.
729.
730.
731.
732.
733.
734.
735.
736.
737.
738.
739.
740.
741.
742.
743.
744.
745.
746.
747.
748.
749.
750.
751.
752.
753.
754.
755.
756.
757.
758.
759.
760.
761.
762.
763.
764.
765.
766.
767.
768.
769.
770.
771.
772.
773.
774.
775.
776.
777.
778.
779.
780.
781.
782.
783.
784.
785.
786.
787.
788.
789.
790.
791.
792.
793.
794.
795.
796.
797.
798.
799.
800.
801.
802.
803.
804.
805.
806.
807.
808.
809.
810.
811.
812.
813.
814.
815.
816.
817.
818.
819.
820.
821.
822.
823.
824.
825.
826.
827.
828.
829.
830.
831.
832.
833.
834.
835.
836.
837.
838.
839.
840.
841.
842.
843.
844.
845.
846.
847.
848.
849.
850.
851.
852.
853.
854.
855.
856.
857.
858.
859.
860.
861.
862.
863.
864.
865.
866.
867.
868.
869.
870.
871.
872.
873.
874.
875.
876.
877.
878.
879.
880.
881.
882.
883.
884.
885.
886.
887.
888.
889.
890.
891.
892.
893.
894.
895.
896.
897.
898.
899.
900.
901.
902.
903.
904.
905.
906.
907.
908.
909.
910.
911.
912.
913.
914.
915.
916.
917.
918.
919.
920.
921.
922.
923.
924.
925.
926.
927.
928.
929.
930.
931.
932.
933.
934.
935.
936.
937.
938.
939.
940.
941.
942.
943.
944.
945.
946.
947.
948.
949.
950.
951.
952.
953.
954.
955.
956.
957.
958.
959.
960.
961.
962.
963.
964.
965.
966.
967.
968.
969.
970.
971.
972.
973.
974.
975.
976.
977.
978.
979.
980.
981.
982.
983.
984.
985.
986.
987.
988.
989.
990.
991.
992.
993.
994.
995.
996.
997.
998.
999.
1000.
1001.
1002.
1003.
1004.
1005.
1006.
1007.
1008.
1009.
Imports System.Net.Sockets
Imports System.Net.Security
Imports System.IO
Imports System.Text

Module ModulePop3

  Public Sub GetMail(ByVal m_PopServer As String, ByVal m_User As String, ByVal m_Password As String, _
   Optional ByVal m_ServerPort As Integer = 110, Optional ByVal m_useSSL As Boolean = False, _
   Optional ByVal m_DeleteEmails As Boolean = True, Optional ByVal m_SaveDir As String = vbNullString, _
   Optional ByVal m_SaveMailPrefix As String = "MSG", Optional ByVal m_SaveMailExt As String = ".eml", _
   Optional ByVal m_TraceFunction As Pop3.TraceHandler = Nothing, Optional ByVal m_TestMode As Boolean = False)

    If m_TraceFunction IsNot Nothing AndAlso m_TestMode = False Then m_TraceFunction("-------------------------")
    Try
      ' prepare pop client
      Dim POP3Client As Pop3.cPop3MailClient = _
       New Pop3.cPop3MailClient(m_PopServer, m_ServerPort, m_useSSL, m_User, m_Password)
      POP3Client.IsAutoReconnect = True

      'if tracing needed
      If m_TraceFunction IsNot Nothing Then AddHandler POP3Client.Trace, m_TraceFunction

      POP3Client.ReadTimeout = 60000 'give pop server 60 seconds to answer

      'establish connection
      POP3Client.Connect()

      'get mailbox statistics
      Dim NumberOfMails As Integer, MailboxSize As Integer
      POP3Client.GetMailboxStats(NumberOfMails, MailboxSize)

      If m_TestMode Then
        'get a list of mails
        Dim EmailIds As New List(Of Integer)
        POP3Client.GetEmailIdList(EmailIds)

        'get a list of unique mail ids
        Dim EmailUids As New List(Of Pop3.EmailUid)
        POP3Client.GetUniqueEmailIdList(EmailUids)

        'only show info
        If NumberOfMails > 0 Then
          For i As Integer = 1 To NumberOfMails
            'get email size
            POP3Client.GetEmailSize(i)
          Next
        End If

        'ping server
        POP3Client.NOOP()

      Else

        'get emails
        If NumberOfMails > 0 Then

          If Strings.Len(m_SaveDir) = 0 OrElse IO.Directory.Exists(m_SaveDir) = False Then _
           m_SaveDir = Application.StartupPath
          If Strings.Len(m_SaveMailPrefix) = 0 Then m_SaveMailPrefix = "MSG"
          If Strings.Len(m_SaveMailExt) = 0 Then m_SaveMailExt = ".eml"
          If Strings.Left(m_SaveMailExt, 1) <> "." Then m_SaveMailExt = "." & m_SaveMailExt

          For i As Integer = 1 To NumberOfMails
            'get email size
            POP3Client.GetEmailSize(i)

            'get email
            Dim Email As String = ""
            POP3Client.GetRawEmail(i, Email)
            If Strings.Len(Email) > 0 Then
              Dim fToSave As String = GetNextEmailFileName(m_SaveDir, m_SaveMailPrefix, m_SaveMailExt)
              Try : IO.File.WriteAllText(fToSave, Email, System.Text.Encoding.ASCII) : Catch : End Try
            End If

            'delete email
            If m_DeleteEmails Then POP3Client.DeleteEmail(i)
          Next
        End If
      End If

      'close connection
      POP3Client.Disconnect()

    Catch ex As Exception
      If m_TraceFunction IsNot Nothing Then
        m_TraceFunction("Run Time Error Occured:")
        m_TraceFunction(ex.Message)
        m_TraceFunction(ex.StackTrace)
      End If
    End Try
    If m_TraceFunction IsNot Nothing AndAlso m_TestMode = False Then m_TraceFunction("-------------------------")

  End Sub

  Private Function GetNextEmailFileName(ByVal path As String, ByVal pref As String, ByVal ext As String) As String
    Dim tmp_name As String
    Dim i As Integer = 0
    Do
      i = i + 1
      tmp_name = IO.Path.Combine(path, pref & i.ToString & ext)
      If IO.File.Exists(tmp_name) = False Then Return tmp_name
    Loop
  End Function

End Module

Namespace Pop3
  ' Supporting classes and structs
  ' ==============================

  ''' <summary>
  ''' Combines Email ID with Email UID for one email
  ''' The POP3 server assigns to each message a unique Email UID, which will not change for the life time
  ''' of the message and no other message should use the same.
  ''' 
  ''' Exceptions:
  ''' Throws Pop3Exception if there is a serious communication problem with the POP3 server, otherwise
  ''' 
  ''' </summary>
  Public Structure EmailUid
    ''' <summary>
    ''' used in POP3 commands to indicate which message (only valid in the present session)
    ''' </summary>
    Public EmailId As Integer
    ''' <summary>
    ''' Uid is always the same for a message, regardless of session
    ''' </summary>
    Public Uid As String

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="EmailId"></param>
    ''' <param name="Uid"></param>
    Public Sub New(EmailId As Integer, Uid As String)
      Me.EmailId = EmailId
      Me.Uid = Uid
    End Sub
  End Structure

  ''' <summary>
  ''' If anything goes wrong within Pop3MailClient, a Pop3Exception is raised
  ''' </summary>
  Public Class Pop3Exception
    Inherits ApplicationException
    ''' <summary>
    ''' 
    ''' </summary>
    Public Sub New()
    End Sub
    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="ErrorMessage"></param>
    Public Sub New(ByVal ErrorMessage As String)
      MyBase.New(ErrorMessage)
    End Sub
  End Class

  ''' <summary>
  ''' A pop 3 connection goes through the following states:
  ''' </summary>
  Public Enum Pop3ConnectionStateEnum
    ''' <summary>
    ''' undefined
    ''' </summary>
    None = 0
    ''' <summary>
    ''' not connected yet to POP3 server
    ''' </summary>
    Disconnected
    ''' <summary>
    ''' TCP connection has been opened and the POP3 server has sent the greeting. POP3 server expects user name and password
    ''' </summary>
    Authorization
    ''' <summary>
    ''' client has identified itself successfully with the POP3, server has locked all messages 
    ''' </summary>
    Connected
    ''' <summary>
    ''' QUIT command was sent, the server has deleted messages marked for deletion and released the resources
    ''' </summary>
    Closed
  End Enum

  ' Delegates for Pop3MailClient
  ' ============================

  ''' <summary>
  ''' If POP3 Server doesn't react as expected or this code has a problem, but
  ''' can continue with the execution, a Warning is called.
  ''' </summary>
  ''' <param name="WarningText"></param>
  ''' <param name="Response">string received from POP3 server</param>
  Public Delegate Sub WarningHandler(ByVal WarningText As String, ByVal Response As String)

  ''' <summary>
  ''' Traces all the information exchanged between POP3 client and POP3 server plus some
  ''' status messages from POP3 client.
  ''' Helpful to investigate any problem.
  ''' Console.WriteLine() can be used
  ''' </summary>
  ''' <param name="TraceText"></param>
  Public Delegate Sub TraceHandler(ByVal TraceText As String)

  ' cPop3MailClient Class
  ' ====================  

  ''' <summary>
  ''' provides access to emails on a POP3 Server
  ''' </summary>
  Public Class cPop3MailClient

    'Events
    '------

    ''' <summary>
    ''' Called whenever POP3 server doesn't react as expected, but no runtime error is thrown.
    ''' </summary>
    Public Event Warning As WarningHandler

    ''' <summary>
    ''' call warning event
    ''' </summary>
    ''' <param name="methodName">name of the method where warning is needed</param>
    ''' <param name="response">answer from POP3 server causing the warning</param>
    ''' <param name="warningText">explanation what went wrong</param>
    ''' <param name="warningParameters"></param>
    Protected Sub CallWarning(ByVal methodName As String, ByVal response As String, _
     ByVal warningText As String, ByVal ParamArray warningParameters As Object())
      warningText = String.Format(warningText, warningParameters)
      RaiseEvent Warning(Convert.ToString(methodName & Convert.ToString(": ")) & warningText, response)
      CallTrace("!! {0}", warningText)
    End Sub

    ''' <summary>
    ''' Shows the communication between PopClient and PopServer, including warnings
    ''' </summary>
    Public Event Trace As TraceHandler

    ''' <summary>
    ''' call Trace event
    ''' </summary>
    ''' <param name="text">string to be traced</param>
    ''' <param name="parameters"></param>
    Protected Sub CallTrace(ByVal text As String, ByVal ParamArray parameters As Object())
      'RaiseEvent Trace(DateTime.Now.ToString("hh:mm:ss ") + m_popServer + " " + String.Format(text, parameters))
      RaiseEvent Trace(DateTime.Now.ToString + Chr(9) + m_popServer + Chr(9) + String.Format(text, parameters))
    End Sub

    ''' <summary>
    ''' Trace information received from POP3 server
    ''' </summary>
    ''' <param name="text">string to be traced</param>
    ''' <param name="parameters"></param>
    Protected Sub TraceFrom(ByVal text As String, ByVal ParamArray parameters As Object())
      CallTrace("   " + String.Format(text, parameters))
    End Sub

    'Properties
    '------

    ''' <summary>
    ''' Get POP3 server name
    ''' </summary>
    Public ReadOnly Property PopServer() As String
      Get
        Return m_popServer
      End Get
    End Property
    ''' <summary>
    ''' POP3 server name
    ''' </summary>
    Protected m_popServer As String

    ''' <summary>
    ''' Get POP3 server port
    ''' </summary>
    Public ReadOnly Property Port() As Integer
      Get
        Return m_port
      End Get
    End Property
    ''' <summary>
    ''' POP3 server port
    ''' </summary>
    Protected m_port As Integer

    ''' <summary>
    ''' Should SSL be used for connection with POP3 server ?
    ''' </summary>
    Public ReadOnly Property UseSSL() As Boolean
      Get
        Return m_useSSL
      End Get
    End Property
    ''' <summary>
    ''' Should SSL be used for connection with POP3 server ?
    ''' </summary>
    Private m_useSSL As Boolean

    ''' <summary>
    ''' should Pop3MailClient automatically reconnect if POP3 server has dropped the 
    ''' connection due to a timeout ?
    ''' </summary>
    Public Property IsAutoReconnect() As Boolean
      Get
        Return m_isAutoReconnect
      End Get
      Set(ByVal value As Boolean)
        m_isAutoReconnect = value
      End Set
    End Property
    Private m_isAutoReconnect As Boolean = False
    'timeout has occured, we try to perform an autoreconnect
    Private isTimeoutReconnect As Boolean = False

    ''' <summary>
    ''' Get / set read timeout (miliseconds)
    ''' </summary>
    Public Property ReadTimeout() As Integer
      Get
        Return m_readTimeout
      End Get
      Set(ByVal value As Integer)
        m_readTimeout = value
        If pop3Stream IsNot Nothing AndAlso pop3Stream.CanTimeout Then
          pop3Stream.ReadTimeout = m_readTimeout
        End If
      End Set
    End Property
    ''' <summary>
    ''' POP3 server read timeout
    ''' </summary>
    Protected m_readTimeout As Integer = -1

    ''' <summary>
    ''' Get owner name of mailbox on POP3 server
    ''' </summary>
    Public ReadOnly Property Username() As String
      Get
        Return m_username
      End Get
    End Property
    ''' <summary>
    ''' Owner name of mailbox on POP3 server
    ''' </summary>
    Protected m_username As String

    ''' <summary>
    ''' Get password for mailbox on POP3 server
    ''' </summary>
    Public ReadOnly Property Password() As String
      Get
        Return m_password
      End Get
    End Property
    ''' <summary>
    ''' Password for mailbox on POP3 server
    ''' </summary>
    Protected m_password As String

    ''' <summary>
    ''' Get connection status with POP3 server
    ''' </summary>
    Public ReadOnly Property Pop3ConnectionState() As Pop3ConnectionStateEnum
      Get
        Return m_pop3ConnectionState
      End Get
    End Property
    ''' <summary>
    ''' connection status with POP3 server
    ''' </summary>
    Protected m_pop3ConnectionState As Pop3ConnectionStateEnum = Pop3ConnectionStateEnum.Disconnected

    ' Methods
    ' -------

    ''' <summary>
    ''' set POP3 connection state
    ''' </summary>
    ''' <param name="State"></param>
    Protected Sub setPop3ConnectionState(ByVal State As Pop3ConnectionStateEnum)
      m_pop3ConnectionState = State
      CallTrace("   Pop3MailClient Connection State {0} reached", State)
    End Sub

    ''' <summary>
    ''' throw exception if POP3 connection is not in the required state
    ''' </summary>
    ''' <param name="requiredState"></param>
    Protected Sub EnsureState(ByVal requiredState As Pop3ConnectionStateEnum)
      If m_pop3ConnectionState <> requiredState Then
        ' wrong connection state
        Throw New Pop3Exception("GetMailboxStats only accepted during connection state: " + requiredState.ToString() + _
         vbLf & " The connection to server " + m_popServer + " is in state " + m_pop3ConnectionState.ToString())
      End If
    End Sub

    'private fields
    '--------------
    ''' <summary>
    ''' TCP to POP3 server
    ''' </summary>
    Private serverTcpConnection As TcpClient
    ''' <summary>
    ''' Stream from POP3 server with or without SSL
    ''' </summary>
    Private pop3Stream As Stream
    ''' <summary>
    ''' Reader for POP3 message
    ''' </summary>
    Protected pop3StreamReader As StreamReader
    ''' <summary>
    ''' char 'array' for carriage return / line feed
    ''' </summary>
    Protected CRLF As String = vbCr & vbLf

    'public methods
    '--------------

    ''' <summary>
    ''' Make POP3 client ready to connect to POP3 server
    ''' </summary>
    ''' <param name="PopServer"><example>pop.gmail.com</example></param>
    ''' <param name="Port"><example>995</example></param>
    ''' <param name="useSSL">True: SSL is used for connection to POP3 server</param>
    ''' <param name="Username"><example>abc@gmail.com<;/example></param>
    ''' <param name="Password">Secret</param>
    Public Sub New(ByVal PopServer As String, ByVal Port As Integer, ByVal useSSL As Boolean, _
     ByVal Username As String, ByVal Password As String)
      Me.m_popServer = PopServer
      Me.m_port = Port
      Me.m_useSSL = useSSL
      Me.m_username = Username
      Me.m_password = Password
    End Sub

    ''' <summary>
    ''' Connect to POP3 server
    ''' </summary>
    Public Sub Connect()
      If (m_pop3ConnectionState <> Pop3ConnectionStateEnum.Disconnected) AndAlso
       (m_pop3ConnectionState <> Pop3ConnectionStateEnum.Closed) AndAlso
       (Not isTimeoutReconnect) Then
        CallWarning("connect", "", "Connect command received, but connection state is: " + m_pop3ConnectionState.ToString())
      Else
        'establish TCP connection
        Try
          CallTrace("   Connect at port {0}", m_port)
          serverTcpConnection = New TcpClient(m_popServer, m_port)
        Catch ex As Exception
          Throw New Pop3Exception("Connection to server " + m_popServer + ", port " + m_port.ToString + " failed." & vbLf & "Runtime Error: " + ex.ToString())
        End Try

        If m_useSSL Then
          'get SSL stream
          Try
            CallTrace("   Get SSL connection")
            pop3Stream = New SslStream(serverTcpConnection.GetStream(), False)
            pop3Stream.ReadTimeout = m_readTimeout
          Catch ex As Exception
            Throw New Pop3Exception("Server " + m_popServer + " found, but cannot get SSL data stream." & vbLf & "Runtime Error: " + ex.ToString())
          End Try

          'perform SSL authentication
          Try
            CallTrace("   Get SSL authentication")
            DirectCast(pop3Stream, SslStream).AuthenticateAsClient(m_popServer)
          Catch ex As Exception
            Throw New Pop3Exception("Server " + m_popServer + " found, but problem with SSL Authentication." & vbLf & "Runtime Error: " + ex.ToString())
          End Try
        Else
          'create a stream to POP3 server without using SSL
          Try
            CallTrace("   Get connection without SSL")
            pop3Stream = serverTcpConnection.GetStream()
            pop3Stream.ReadTimeout = m_readTimeout
          Catch ex As Exception
            Throw New Pop3Exception("Server " + m_popServer + " found, but cannot get data stream (without SSL)." & vbLf & "Runtime Error: " + ex.ToString())
          End Try
        End If

        'get stream for reading from pop server
        'POP3 allows only US-ASCII. The message will be translated in the proper encoding in a later step
        Try
          pop3StreamReader = New StreamReader(pop3Stream, Encoding.ASCII)
        Catch ex As Exception
          If m_useSSL Then
            Throw New Pop3Exception("Server " + m_popServer + " found, but cannot read from SSL stream." & vbLf & "Runtime Error: " + ex.ToString())
          Else
            Throw New Pop3Exception("Server " + m_popServer + " found, but cannot read from stream (without SSL)." & vbLf & "Runtime Error: " + ex.ToString())
          End If
        End Try

        'ready for authorisation
        Dim response As String = ""
        If Not readSingleLine(response) Then
          Throw New Pop3Exception(Convert.ToString("Server " + m_popServer + " not ready to start AUTHORIZATION." & vbLf & "Message: ") & response)
        End If
        setPop3ConnectionState(Pop3ConnectionStateEnum.Authorization)

        'send user name
        If Not executeCommand("USER " + m_username, response) Then
          Throw New Pop3Exception(Convert.ToString("Server " + m_popServer + " doesn't accept username '" + m_username + "'." & vbLf & "Message: ") & response)
        End If

        'send password
        If Not executeCommand("PASS " + m_password, response) Then
          Throw New Pop3Exception(Convert.ToString("Server " + m_popServer + " doesn't accept password '" + m_password + "' for user '" + m_username + "'." & vbLf & "Message: ") & response)
        End If

        setPop3ConnectionState(Pop3ConnectionStateEnum.Connected)
      End If
    End Sub

    ''' <summary>
    ''' Disconnect from POP3 Server
    ''' </summary>
    Public Sub Disconnect()
      If m_pop3ConnectionState = Pop3ConnectionStateEnum.Disconnected OrElse _
       m_pop3ConnectionState = Pop3ConnectionStateEnum.Closed Then
        CallWarning("disconnect", "", "Disconnect received, but was already disconnected.")
      Else
        'ask server to end session and possibly to remove emails marked for deletion
        Try
          Dim response As String = ""
          If executeCommand("QUIT", response) Then
            'server says everything is ok
            setPop3ConnectionState(Pop3ConnectionStateEnum.Closed)
          Else
            'server says there is a problem
            CallWarning("Disconnect", response, Convert.ToString("negative response from server while closing connection: ") & response)
            setPop3ConnectionState(Pop3ConnectionStateEnum.Disconnected)
          End If
        Finally
          'close connection
          If pop3Stream IsNot Nothing Then
            pop3Stream.Close()
          End If

          pop3StreamReader.Close()
        End Try
      End If
    End Sub

    ''' <summary>
    ''' Delete message from server.
    ''' The POP3 server marks the message as deleted.  Any future
    ''' reference to the message-number associated with the message
    ''' in a POP3 command generates an error.  The POP3 server does
    ''' not actually delete the message until the POP3 session
    ''' enters the UPDATE state.
    ''' </summary>
    ''' <param name="msg_number"></param>
    ''' <returns></returns>
    Public Function DeleteEmail(ByVal msg_number As Integer) As Boolean
      EnsureState(Pop3ConnectionStateEnum.Connected)
      Dim response As String = ""
      If Not executeCommand("DELE " + msg_number.ToString(), response) Then
        CallWarning("DeleteEmail", response, "negative response for email (Id: {0}) delete request", msg_number)
        Return False
      End If
      Return True
    End Function

    ''' <summary>
    ''' Get a list of all Email IDs available in mailbox
    ''' </summary>
    ''' <returns></returns>
    Public Function GetEmailIdList(ByRef EmailIds As List(Of Integer)) As Boolean
      EnsureState(Pop3ConnectionStateEnum.Connected)
      EmailIds = New List(Of Integer)()

      'get server response status line
      Dim response As String = ""
      If Not executeCommand("LIST", response) Then
        CallWarning("GetEmailIdList", response, "negative response for email list request")
        Return False
      End If

      'get every email id
      Dim EmailId As Integer
      While readMultiLine(response)
        If Integer.TryParse(response.Split(" "c)(0), EmailId) Then
          EmailIds.Add(EmailId)
        Else
          CallWarning("GetEmailIdList", response, "first characters should be integer (EmailId)")
        End If
      End While
      TraceFrom("{0} email ids received", EmailIds.Count)
      Return True
    End Function

    ''' <summary>
    ''' get size of one particular email
    ''' </summary>
    ''' <param name="msg_number"></param>
    ''' <returns></returns>
    Public Function GetEmailSize(ByVal msg_number As Integer) As Integer
      EnsureState(Pop3ConnectionStateEnum.Connected)
      Dim response As String = ""
      executeCommand("LIST " + msg_number.ToString(), response)
      Dim EmailSize As Integer = 0
      Dim responseSplit As String() = response.Split(" "c)
      If responseSplit.Length < 2 OrElse Not Integer.TryParse(responseSplit(2), EmailSize) Then
        CallWarning("GetEmailSize", response, "'+OK int int' format expected (EmailId, EmailSize)")
      End If

      Return EmailSize
    End Function

    ''' <summary>
    ''' Get a list with the unique IDs of all Email available in mailbox.
    ''' 
    ''' Explanation:
    ''' EmailIds for the same email can change between sessions, whereas the unique Email id
    ''' never changes for an email.
    ''' </summary>
    ''' <param name="EmailIds"></param>
    ''' <returns></returns>
    Public Function GetUniqueEmailIdList(ByRef EmailIds As List(Of EmailUid)) As Boolean
      EnsureState(Pop3ConnectionStateEnum.Connected)
      EmailIds = New List(Of EmailUid)()

      'get server response status line
      Dim response As String = ""
      If Not executeCommand("UIDL ", response) Then
        CallWarning("GetUniqueEmailIdList", response, "negative response for email list request")
        Return False
      End If

      'get every email unique id
      Dim EmailId As Integer
      While readMultiLine(response)
        Dim responseSplit As String() = response.Split(" "c)
        If responseSplit.Length < 2 Then
          CallWarning("GetUniqueEmailIdList", response, "response not in format 'int string'")
        ElseIf Not Integer.TryParse(responseSplit(0), EmailId) Then
          CallWarning("GetUniqueEmailIdList", response, "first charaters should be integer (Unique EmailId)")
        Else
          EmailIds.Add(New EmailUid(EmailId, responseSplit(1)))
        End If
      End While
      TraceFrom("{0} unique email ids received", EmailIds.Count)
      Return True
    End Function

    ''' <summary>
    ''' get a list with all currently available messages and the UIDs
    ''' </summary>
    ''' <param name="EmailIds">EmailId Uid list</param>
    ''' <returns>false: server sent negative response (didn't send list)</returns>
    Public Function GetUniqueEmailIdList(ByRef EmailIds As SortedList(Of String, Integer)) As Boolean
      EnsureState(Pop3ConnectionStateEnum.Connected)
      EmailIds = New SortedList(Of String, Integer)()

      'get server response status line
      Dim response As String = ""
      If Not executeCommand("UIDL", response) Then
        CallWarning("GetUniqueEmailIdList", response, "negative response for email list request")
        Return False
      End If

      'get every email unique id
      Dim EmailId As Integer
      While readMultiLine(response)
        Dim responseSplit As String() = response.Split(" "c)
        If responseSplit.Length < 2 Then
          CallWarning("GetUniqueEmailIdList", response, "response not in format 'int string'")
        ElseIf Not Integer.TryParse(responseSplit(0), EmailId) Then
          CallWarning("GetUniqueEmailIdList", response, "first charaters should be integer (Unique EmailId)")
        Else
          EmailIds.Add(responseSplit(1), EmailId)
        End If
      End While
      TraceFrom("{0} unique email ids received", EmailIds.Count)
      Return True
    End Function

    ''' <summary>
    ''' get size of one particular email
    ''' </summary>
    ''' <param name="msg_number"></param>
    ''' <returns></returns>
    Public Function GetUniqueEmailId(ByVal msg_number As EmailUid) As Integer
      EnsureState(Pop3ConnectionStateEnum.Connected)
      Dim response As String = ""
      executeCommand("LIST " + msg_number.ToString(), response)
      Dim EmailSize As Integer = 0
      Dim responseSplit As String() = response.Split(" "c)
      If responseSplit.Length < 2 OrElse Not Integer.TryParse(responseSplit(2), EmailSize) Then
        CallWarning("GetEmailSize", response, "'+OK int int' format expected (EmailId, EmailSize)")
      End If

      Return EmailSize
    End Function

    ''' <summary>
    ''' Sends an 'empty' command to the POP3 server. Server has to respond with +OK
    ''' </summary>
    ''' <returns>true: server responds as expected</returns>
    Public Function NOOP() As Boolean
      EnsureState(Pop3ConnectionStateEnum.Connected)
      Dim response As String = ""
      If Not executeCommand("NOOP", response) Then
        CallWarning("NOOP", response, "negative response for NOOP request")
        Return False
      End If
      Return True
    End Function

    ''' <summary>
    ''' Should the raw content, the US-ASCII code as received, be traced
    ''' GetRawEmail will switch it on when it starts and off once finished
    ''' 
    ''' Inheritors might use it to get the raw email
    ''' </summary>
    Protected isTraceRawEmail As Boolean = False


    ''' <summary>
    ''' contains one MIME part of the email in US-ASCII, needs to be translated in .NET string (Unicode)
    ''' contains the complete email in US-ASCII, needs to be translated in .NET string (Unicode)
    ''' For speed reasons, reuse StringBuilder
    ''' </summary>
    Protected RawEmailSB As StringBuilder

    ''' <summary>
    ''' Reads the complete text of a message
    ''' </summary>
    ''' <param name="MessageNo">Email to retrieve</param>
    ''' <param name="EmailText">ASCII string of complete message</param>
    ''' <returns></returns>
    Public Function GetRawEmail(ByVal MessageNo As Integer, ByRef EmailText As String) As Boolean
      'send 'RETR int' command to server
      If Not SendRetrCommand(MessageNo) Then
        EmailText = Nothing
        Return False
      End If

      'get the lines
      Dim response As String = ""
      Dim LineCounter As Integer = 0
      'empty StringBuilder
      If RawEmailSB Is Nothing Then
        RawEmailSB = New StringBuilder(100000)
      Else
        RawEmailSB.Length = 0
      End If
      isTraceRawEmail = True
      While readMultiLine(response)
        LineCounter += 1
      End While
      EmailText = RawEmailSB.ToString()
      TraceFrom("email with {0} lines,  {1} chars received", LineCounter.ToString(), EmailText.Length)
      Return True
    End Function

    ' ''' <summary>
    ' ''' Requests from POP3 server a specific email and returns a stream with the message content (header and body)
    ' ''' </summary>
    ' ''' <param name="MessageNo"></param>
    ' ''' <param name="EmailStreamReader"></param>
    ' ''' <returns>false: POP3 server cannot provide this message</returns>
    'Public Function GetEmailStream(ByVal MessageNo As Integer, ByRef EmailStreamReader As StreamReader) As Boolean
    '  'send 'RETR int' command to server
    '  If Not SendRetrCommand(MessageNo) Then
    '    EmailStreamReader = Nothing
    '    Return False
    '  End If
    '  EmailStreamReader = sslStreamReader
    '  Return True
    'End Function

    ''' <summary>
    ''' Unmark any emails from deletion. The server only deletes email really
    ''' once the connection is properly closed.
    ''' </summary>
    ''' <returns>true: emails are unmarked from deletion</returns>
    Public Function UndeleteAllEmails() As Boolean
      EnsureState(Pop3ConnectionStateEnum.Connected)
      Dim response As String = ""
      Return executeCommand("RSET", response)
    End Function

    ''' <summary>
    ''' Get mailbox statistics
    ''' </summary>
    ''' <param name="NumberOfMails"></param>
    ''' <param name="MailboxSize"></param>
    ''' <returns></returns>
    Public Function GetMailboxStats(ByRef NumberOfMails As Integer, ByRef MailboxSize As Integer) As Boolean
      EnsureState(Pop3ConnectionStateEnum.Connected)

      'interpret response
      Dim response As String = ""
      NumberOfMails = 0
      MailboxSize = 0
      If executeCommand("STAT", response) Then
        'got a positive response
        Dim responseParts As String() = response.Split(" "c)
        If responseParts.Length < 2 Then
          'response format wrong
          Throw New Pop3Exception(Convert.ToString("Server " + m_popServer + " sends illegally formatted response." + _
           vbLf & "Expected format: +OK int int" + _
           vbLf & "Received response: ") & response)
        End If
        NumberOfMails = Integer.Parse(responseParts(1))
        MailboxSize = Integer.Parse(responseParts(2))
        Return True
      End If
      Return False
    End Function

    ''' <summary>
    ''' Send RETR command to POP 3 server to fetch one particular message
    ''' </summary>
    ''' <param name="MessageNo">ID of message required</param>
    ''' <returns>false: negative server respond, message not delivered</returns>
    Protected Function SendRetrCommand(ByVal MessageNo As Integer) As Boolean
      EnsureState(Pop3ConnectionStateEnum.Connected)
      ' retrieve mail with message number
      Dim response As String = ""
      If Not executeCommand("RETR " + MessageNo.ToString(), response) Then
        CallWarning("GetRawEmail", response, "negative response for email (ID: {0}) request", MessageNo)
        Return False
      End If
      Return True
    End Function

    'Helper methodes
    '---------------

    Public isDebug As Boolean = False

    ''' <summary>
    ''' sends the 4 letter command to POP3 server (adds CRLF) and waits for the
    ''' response of the server
    ''' </summary>
    ''' <param name="command">command to be sent to server</param>
    ''' <param name="response">answer from server</param>
    ''' <returns>false: server sent negative acknowledge, i.e. server could not execute command</returns>
    Private Function executeCommand(ByVal command As String, ByRef response As String) As Boolean
      'send command to server
      Dim commandBytes As Byte() = System.Text.Encoding.ASCII.GetBytes((command & CRLF).ToCharArray())
      CallTrace("Tx '{0}'", command)
      Dim isSupressThrow As Boolean = False
      Try
        pop3Stream.Write(commandBytes, 0, commandBytes.Length)
        If isDebug Then
          isDebug = False
          Throw New IOException("Test", New SocketException(10053))
        End If
      Catch ex As IOException
        'Unable to write data to the transport connection. Check if reconnection should be tried
        isSupressThrow = executeReconnect(ex, command, commandBytes)
        If Not isSupressThrow Then
          Throw
        End If
      End Try
      pop3Stream.Flush()

      'read response from server
      response = Nothing
      Try
        response = pop3StreamReader.ReadLine()
      Catch ex As IOException
        'Unable to write data to the transport connection. Check if reconnection should be tried
        isSupressThrow = executeReconnect(ex, command, commandBytes)
        If isSupressThrow Then
          'wait for response one more time
          response = pop3StreamReader.ReadLine()
        Else
          Throw
        End If
      End Try
      If response Is Nothing Then
        Throw New Pop3Exception("Server " + m_popServer + " has not responded, timeout has occured.")
      End If
      CallTrace("Rx '{0}'", response)
      Return (response.Length > 0 AndAlso response(0) = "+"c)
    End Function

    ''' <summary>
    ''' reconnect, if there is a timeout exception and isAutoReconnect is true
    ''' 
    ''' </summary>
    Private Function executeReconnect(ByVal ex As IOException, ByVal command As String, _
     ByVal commandBytes As Byte()) As Boolean
      If ex.InnerException IsNot Nothing AndAlso TypeOf ex.InnerException Is SocketException Then
        'SocketException
        Dim innerEx As SocketException = DirectCast(ex.InnerException, SocketException)
        If innerEx.ErrorCode = 10053 Then
          'probably timeout: An established connection was aborted by the software in your host machine.
          CallWarning("ExecuteCommand", "", "probably timeout occured")
          If m_isAutoReconnect Then
            'try to reconnect and send one more time
            isTimeoutReconnect = True
            Try
              CallTrace("   try to auto reconnect")
              Connect()

              CallTrace("   reconnect successful, try to resend command")
              CallTrace("Tx '{0}'", command)
              pop3Stream.Write(commandBytes, 0, commandBytes.Length)
              pop3Stream.Flush()
              Return True
            Finally
              isTimeoutReconnect = False
            End Try

          End If
        End If
      End If
      Return False
    End Function

    ' ''' <summary>
    ' ''' sends the 4 letter command to POP3 server (adds CRLF)
    ' ''' </summary>
    ' ''' <param name="command"></param>
    'Protected Sub SendCommand(ByVal command As String)
    '  Dim commandBytes As Byte() = System.Text.Encoding.ASCII.GetBytes((command & CRLF).ToCharArray())
    '  CallTrace("Tx '{0}'", command)
    '  Try
    '    pop3Stream.Write(commandBytes, 0, commandBytes.Length)
    '  Catch ex As IOException
    '    'Unable to write data to the transport connection:
    '    If ex.InnerException IsNot Nothing AndAlso TypeOf ex.InnerException Is SocketException Then
    '      'SocketException
    '      Dim innerEx As SocketException = DirectCast(ex.InnerException, SocketException)
    '      If innerEx.ErrorCode = 10053 Then
    '        'probably timeout: An established connection was aborted by the software in your host machine.
    '        CallWarning("SendCommand", "", "probably timeout occured")
    '        If m_isAutoReconnect Then
    '          'try to reconnect and send one more time
    '          isTimeoutReconnect = True
    '          Try
    '            CallTrace("   try to auto reconnect")
    '            Connect()

    '            CallTrace("   reconnect successful, try to resend command")
    '            CallTrace("Tx '{0}'", command)
    '            pop3Stream.Write(commandBytes, 0, commandBytes.Length)
    '          Finally
    '            isTimeoutReconnect = False
    '          End Try
    '          Return
    '        End If
    '      End If
    '    End If
    '    Throw
    '  End Try
    '  pop3Stream.Flush()
    'End Sub

    ''' <summary>
    ''' read single line response from POP3 server. 
    ''' <example>Example server response: +OK asdfkjahsf</example>
    ''' </summary>
    ''' <param name="response">response from POP3 server</param>
    ''' <returns>true: positive response</returns>
    Protected Function readSingleLine(ByRef response As String) As Boolean
      response = Nothing
      Try
        response = pop3StreamReader.ReadLine()
      Catch ex As Exception
        Dim s As String = ex.Message
      End Try
      If response Is Nothing Then
        Throw New Pop3Exception("Server " + m_popServer + " has not responded, timeout has occured.")
      End If
      CallTrace("Rx '{0}'", response)
      Return (response.Length > 0 AndAlso response(0) = "+"c)
    End Function

    ''' <summary>
    ''' read one line in multiline mode from the POP3 server. 
    ''' </summary>
    ''' <param name="response">line received</param>
    ''' <returns>false: end of message</returns>
    Protected Function readMultiLine(ByRef response As String) As Boolean
      response = Nothing
      response = pop3StreamReader.ReadLine()
      If response Is Nothing Then
        Throw New Pop3Exception("Server " + m_popServer + " has not responded, probably timeout has occured.")
      End If
      If isTraceRawEmail Then
        'collect all responses as received
        RawEmailSB.Append(response & CRLF)
      End If
      'check for byte stuffing, i.e. if a line starts with a '.', another '.' is added, unless
      'it is the last line
      If response.Length > 0 AndAlso response(0) = "."c Then
        If response = "." Then
          'closing line found
          Return False
        End If
        'remove the first '.'
        response = response.Substring(1, response.Length - 1)
      End If
      Return True
    End Function

  End Class

End Namespace


то мне его просто надо переделать в IMAP? Насколько тяжело?

Ну, вот POP3 дебаг(скачиваем единственное письмо, с удалением на сервере)

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
19.05.2015 16:41:23	pop.gmail.com	   Connect at port 995
19.05.2015 16:41:23	pop.gmail.com	   Get SSL connection
19.05.2015 16:41:23	pop.gmail.com	   Get SSL authentication
19.05.2015 16:41:23	pop.gmail.com	Rx '+OK Gpop ready for requests from 176.17.213.145 c128mb48153737lfb'
19.05.2015 16:41:23	pop.gmail.com	   Pop3MailClient Connection State Authorization reached
19.05.2015 16:41:23	pop.gmail.com	Tx 'USER username@gmail.com'
19.05.2015 16:41:23	pop.gmail.com	Rx '+OK send PASS'
19.05.2015 16:41:23	pop.gmail.com	Tx 'PASS password'
19.05.2015 16:41:25	pop.gmail.com	Rx '+OK Welcome.'
19.05.2015 16:41:25	pop.gmail.com	   Pop3MailClient Connection State Connected reached



Не получится это в лоб переделать и вот почему:
Вот начало общения imap.
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
20.05.2015 15:46:31	imap.gmail.com	   Connect at port 993
20.05.2015 15:46:31	imap.gmail.com	   Get SSL connection
20.05.2015 15:46:31	imap.gmail.com	   Get SSL authentication
20.05.2015 15:46:31	imap.gmail.com	Rx '* OK Gimap ready for requests from 176.16.213.147 m9mb59377491ldr'
20.05.2015 15:46:31	imap.gmail.com	   Pop3MailClient Connection State Authorization reached
20.05.2015 15:46:31	imap.gmail.com	Tx '. LOGIN username@gmail.com password'
20.05.2015 15:46:32	imap.gmail.com	Rx '* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 UIDPLUS COMPRESS=DEFLATE ENABLE MOVE CONDSTORE ESEARCH UTF8=ACCEPT'
20.05.2015 15:46:32	imap.gmail.com	Rx '. OK username@gmail.com authenticated (Success)'
20.05.2015 15:46:32	imap.gmail.com	   Pop3MailClient Connection State Connected reached


Принципы общения разные.
pop: >команда <ответ
imap: >команда * отсебятина от сервера в любом месте <ответ

Т.е. код для pop3 базируется на методе
->pop3Stream.Write
<-response = pop3StreamReader.ReadLine()
(в крайнем случае несколько раз, но всегда знает сколько строк читать)

А в случае imap (принцип у него такой) сервер в любом месте может выдать строчку без тага (со звездочкой) типа выделенной Rx '* CAPABILITY IMAP4rev1
(в приведенном логе я искуственно прочитал лишнюю, отбросив ту что со звездочкой)

Как написано в документации, читать надо непрерывно (соответственно одним потоком и линейными функциями уже не отделаешься). Надо отдельно слать команды и независимо их читать (висеть на pop3StreamReader).
Но это как минимум полностью другая логика.
Т.е. для imap надо полностью разносить запись и чтение.
По принципу .ReadLine() висяк в любом месте с "error по таймауту" обеспечен.

В vb6 winsock насколько я помню как раз и висит
Код: vbnet
1.
Public Sub DataArrivalIMAP(Winsock1 As Winsock, ByVal bytesTotal As Long)


Antonariyфишка IMAP - нужно вести сквозную нумерацию отсылаемых команд (A1-A5)
Необязательно. Можешь точку ставить.
Фишка в том, что используя разные таги для разных команд, ты всегда (читая StreamReader) можешь понять что это ответ именно на твой конкретный запрос. Т.е. можешь накидать команд сразу, а он тебе даже не гарантирует что ответы вернутся в той же самой последовательности.
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38964410
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77 Не получится это в лоб переделать и вот почему:Что-то я не понял твоей проблемы. В копипасте, что я дал, полный цикл IMAP-сеанса, который прекрасно работал бы, если бы не баг мэйлру с применением команд. Посмотри, как я там ответ в кучу собираю.

Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
        If Mid$(strData, InStr(strData, " ") + 1, 2) = "OK" Or Mid$(s(0), InStr(s(0), " ") + 1, 2) = "OK" Then
            'ответ закончился, разбираем, шлём новый запрос
        ElseIf InStr(strData, " NO ") = 0 And Mid$(s(0), 1, 1) = "*" Then
            'пришел кусок ответа, плюсуем его
            .BufferString = .BufferString & strData
        Else
            'вернулась ошибка
        End If



Дмитрий77 Принципы общения разные.
а процедуры у меня почти одинаковые почему-то. pop3 для сравнения:
Код: vbnet
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.
Private Sub Winsock1_DataArrival(Index As Integer, ByVal bytesTotal As Long)
    Select Case m_States(Index).Protocol
        Case pSMTP: DataArrivalSMTP Winsock1(Index), bytesTotal
        Case pIMAP: DataArrivalIMAP Winsock1(Index), bytesTotal
    End Select
End Sub

Public Sub DataArrivalSMTP(Winsock1 As Winsock, ByVal bytesTotal As Long)
Dim m_oMessage As CMessage
Dim strData As String
Dim s As String
    On Error GoTo errh
    Winsock1.GetData strData
    With m_States(Winsock1.Index)
        'Debug.Print Winsock1.Index, strData
        If Left$(strData, 1) = "+" Or .State = POP3_TOP Or .State = POP3_RETR Then
            Select Case .State
                Case POP3_Connect
                    .MessagesCount = 0
                    .State = POP3_USER
                    Winsock1.SendData "USER " & .Login & vbCrLf
                Case POP3_USER
                    .State = POP3_PASS
                    Winsock1.SendData "PASS " & .Pass & vbCrLf
                Case POP3_PASS
                    .State = POP3_STAT
                    Winsock1.SendData "STAT" & vbCrLf
                    Debug.Print Winsock1.Index; ">STAT"
                Case POP3_STAT
                    .MessagesCount = CInt(Mid$(strData, 5, InStr(5, strData, " ") - 5))
                    If Not .StateStat Then
                        If .MessagesCount > 0 Then
                            .CurrentMsg = 1 '.MessagesCount
                            .MailCount = .MessagesCount
                            If FastMode Then
                                .State = POP3_TOP
                                Winsock1.SendData "TOP " & .CurrentMsg & " 0" & vbCrLf
                            Else
                                .State = POP3_RETR
                                Winsock1.SendData "RETR " & .CurrentMsg & vbCrLf
                            End If
                        Else
                            .MailCount = 0
                            .State = POP3_QUIT
                            Winsock1.SendData "QUIT" & vbCrLf
                        End If
                    Else
                        .State = POP3_QUIT
                        Winsock1.SendData "QUIT" & vbCrLf
                    End If
                Case POP3_TOP, POP3_RETR
                    .BufferString = .BufferString & strData
                    If InStr(1, .BufferString, vbLf & "." & vbCrLf) Then
                        If InStr(.BufferString, "+") = 1 Then .BufferString = Mid$(.BufferString, InStr(.BufferString, vbCrLf) + 2)
                        .BufferString = Left$(.BufferString, Len(.BufferString) - 3)
                        Set m_oMessage = New CMessage
                        m_oMessage.CreateFromText .BufferString
                        s = CheckMsg(m_oMessage, Winsock1.Index)
                        'Debug.Print Winsock1.Index, s
                        Winsock1.SendData s
                    End If
                Case POP3_QUIT
                    Winsock1.Close
                    .State = POP3_VeryQUIT
                Case POP3_DELE
                    .CurrentMsg = .CurrentMsg + 1
                    .BufferString = ""
                    If .CurrentMsg > .MessagesCount Then
                        .StateStat = True
                        .State = POP3_STAT
                        Winsock1.SendData "STAT" & vbCrLf
                    Else
                        If FastMode Then
                            .State = POP3_TOP
                            Winsock1.SendData "TOP " & .CurrentMsg & " 0" & vbCrLf
                        Else
                            .State = POP3_RETR
                            Winsock1.SendData "RETR " & .CurrentMsg & vbCrLf
                        End If
                    End If
            End Select
        Else
            Winsock1.SendData "QUIT" & vbCrLf
            .State = POP3_QUIT
            .Error = True
        End If
    End With
    Exit Sub
errh:
    With m_States(Winsock1.Index)
        frmReport.ctlProgress1.ErrDesc(Winsock1.Index) = LoadEnumString(, "ProgramError") & "DataArrivalSMTP - " & Err.Description
        Winsock1.Close
        Debug.Print Err.Description
        .State = POP3_VeryQUIT
        .Error = True
    End With
    Exit Sub
    Resume
End Sub

...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38964439
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Antonariy,

Разница между приведенным мной кодом POP3 для .Net в том что у тебя

Код: vbnet
1.
2.
3.
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)

End Sub



непрерывно (и "асинхронно") получает данные "как только так сразу" (событие).

А в моем .Net коде делается
pop3StreamReader.ReadLine() после команды
в том же потоке (предполагая что там должна быть строка, или несколько что для pop3 прогнозируемо, а для imap - нет).

Твой то конечно универсален для обоих случаев.
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38964527
carrotik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77Antonariy,

Разница между приведенным мной кодом POP3 для .Net в том что у тебя

Код: vbnet
1.
2.
3.
Private Sub Winsock1_DataArrival(ByVal bytesTotal As Long)

End Sub



непрерывно (и "асинхронно") получает данные "как только так сразу" (событие).

А в моем .Net коде делается
pop3StreamReader.ReadLine() после команды
в том же потоке (предполагая что там должна быть строка, или несколько что для pop3 прогнозируемо, а для imap - нет).

Твой то конечно универсален для обоих случаев.

...все там прогнозируемо, если посидеть с telnet-ом и покидать нужные команды на сервер :) ... у меня ReadLine вполне справляется, другое дело что требуется поработать над получаемой строкой, пообрезать всякие "OK FETCH COMPLETED" и т.д. .. в коде это выглядит некрасиво, но потом вполне съедобно .. но это если так уж сильно надо, простого рецепта "Взял и поехали" вероятно нет ...
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38964581
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
carrotik,

ну это значит над каждой командой надо "сидеть индивидуально".
В pop3 коде - там немножко стандартизированный разбор (типа одна функция на несколько команд).
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38964583
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
потому что если сделаешь лишнюю ReadLine то по понятным причинам все нафиг зависнет.
А если сделаешь меньше чем надо, то не прочтешь ответ на запрос.
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38964598
Фотография Изопропил
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77потому что если сделаешь лишнюю ReadLine то по понятным причинам все нафиг зависнет.
А если сделаешь меньше чем надо, то не прочтешь ответ на запрос.
нехер инструментарий для хелловорда пользовать
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38964744
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну я передумал сдаваться.
Уже понятно, что завелось.

Мне вот чего непонятно (я на эту тему вопрос задавал).
Письма, удаленные через IMAP на mail.ru получить по POP3 более невозможно. (корректно)
Письма, удаленные через IMAP на gmail.com по POP3 прекрасно потом выкачиваются (некорректно). При этом если слазить на gmail по web-интерфейсу, то после удаления по IMAP письмо из "входящих" перемещается в папку "вся почта".
В этой ситуации если клиент в моей проге настроит IMAP, а потом через месяц-другой перенастроит ее на POP3, то результат очевиден: прога повторно выкачает кучу уже давно принятого мыла. Бардак(с).

С точки зрения IMAP в обоих случаях удаленные по IMAP письма более недоступны.
После выкачки по POP3 по IMAP письма также более недоступны (в обоих случаях).


Код: vbnet
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.
-------------------------
21.05.2015 6:01:15	imap.mail.ru	   Connect at port 993
21.05.2015 6:01:15	imap.mail.ru	   Get SSL connection
21.05.2015 6:01:15	imap.mail.ru	   Get SSL authentication
21.05.2015 6:01:15	imap.mail.ru	Rx '* OK Welcome'
21.05.2015 6:01:15	imap.mail.ru	   Pop3MailClient Connection State Authorization reached
21.05.2015 6:01:15	imap.mail.ru	Tx '. LOGIN username@bk.ru password'
21.05.2015 6:01:15	imap.mail.ru	Rx '* CAPABILITY IMAP4rev1 ID XLIST UIDPLUS UNSELECT MOVE'
21.05.2015 6:01:15	imap.mail.ru	Rx '. OK Authentication successful'
21.05.2015 6:01:15	imap.mail.ru	   Pop3MailClient Connection State Connected reached
21.05.2015 6:01:15	imap.mail.ru	Tx '. SELECT INBOX'
21.05.2015 6:01:15	imap.mail.ru	Rx '* FLAGS (\Answered \Flagged \Deleted \Draft \Seen)'
21.05.2015 6:01:15	imap.mail.ru	Rx '* 1 EXISTS'
21.05.2015 6:01:15	imap.mail.ru	Rx '* 0 RECENT'
21.05.2015 6:01:15	imap.mail.ru	Rx '* OK [UNSEEN 1]'
21.05.2015 6:01:15	imap.mail.ru	Rx '* OK [UIDVALIDITY 1363731524]'
21.05.2015 6:01:15	imap.mail.ru	Rx '* OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft)]'
21.05.2015 6:01:15	imap.mail.ru	Rx '* OK [UIDNEXT 723]'
21.05.2015 6:01:15	imap.mail.ru	Rx '. OK [READ-WRITE] SELECT completed'
21.05.2015 6:01:15	imap.mail.ru	Tx '. FETCH 1 RFC822'
21.05.2015 6:01:15	imap.mail.ru	Rx '* 1 FETCH (RFC822 {2452}'
21.05.2015 6:01:15	imap.mail.ru	Rx '. OK FETCH done'
21.05.2015 6:01:15	imap.mail.ru	   email with 73 lines,  2452 chars received
21.05.2015 6:01:15	imap.mail.ru	Tx '. STORE 1 +FLAGS (\DELETED)'
21.05.2015 6:01:15	imap.mail.ru	Rx '* 1 FETCH (FLAGS (\Seen \Deleted))'
21.05.2015 6:01:15	imap.mail.ru	Rx '. OK STORE done'
21.05.2015 6:01:15	imap.mail.ru	Tx '. EXPUNGE'
21.05.2015 6:01:15	imap.mail.ru	Rx '* 1 EXPUNGE'
21.05.2015 6:01:15	imap.mail.ru	Rx '* 0 EXISTS'
21.05.2015 6:01:15	imap.mail.ru	Rx '. OK EXPUNGE completed'
21.05.2015 6:01:15	imap.mail.ru	Tx '. LOGOUT'
21.05.2015 6:01:15	imap.mail.ru	Rx '* BYE logging out'
21.05.2015 6:01:15	imap.mail.ru	Rx '. OK LOGOUT completed'
21.05.2015 6:01:15	imap.mail.ru	   Pop3MailClient Connection State Closed reached


Код: vbnet
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.
21.05.2015 6:08:11	imap.gmail.com	   Connect at port 993
21.05.2015 6:08:11	imap.gmail.com	   Get SSL connection
21.05.2015 6:08:11	imap.gmail.com	   Get SSL authentication
21.05.2015 6:08:11	imap.gmail.com	Rx '* OK Gimap ready for requests from 176.18.213.120 d70mb67149363lfd'
21.05.2015 6:08:11	imap.gmail.com	   Pop3MailClient Connection State Authorization reached
21.05.2015 6:08:11	imap.gmail.com	Tx '. LOGIN username@gmail.com password'
21.05.2015 6:08:12	imap.gmail.com	Rx '* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 UIDPLUS COMPRESS=DEFLATE ENABLE MOVE CONDSTORE ESEARCH UTF8=ACCEPT'
21.05.2015 6:08:12	imap.gmail.com	Rx '. OK faxvoip@gmail.com authenticated (Success)'
21.05.2015 6:08:12	imap.gmail.com	   Pop3MailClient Connection State Connected reached
21.05.2015 6:08:12	imap.gmail.com	Tx '. SELECT INBOX'
21.05.2015 6:08:12	imap.gmail.com	Rx '* FLAGS (\Answered \Flagged \Draft \Deleted \Seen $Phishing $NotPhishing)'
21.05.2015 6:08:12	imap.gmail.com	Rx '* OK [PERMANENTFLAGS (\Answered \Flagged \Draft \Deleted \Seen $Phishing $NotPhishing \*)] Flags permitted.'
21.05.2015 6:08:12	imap.gmail.com	Rx '* OK [UIDVALIDITY 612224604] UIDs valid.'
21.05.2015 6:08:12	imap.gmail.com	Rx '* 1 EXISTS'
21.05.2015 6:08:12	imap.gmail.com	Rx '* 0 RECENT'
21.05.2015 6:08:12	imap.gmail.com	Rx '* OK [UIDNEXT 5417] Predicted next UID.'
21.05.2015 6:08:12	imap.gmail.com	Rx '* OK [HIGHESTMODSEQ 538412]'
21.05.2015 6:08:12	imap.gmail.com	Rx '. OK [READ-WRITE] INBOX selected. (Success)'
21.05.2015 6:08:12	imap.gmail.com	Tx '. FETCH 1 RFC822'
21.05.2015 6:08:12	imap.gmail.com	Rx '* 1 FETCH (RFC822 {8769}'
21.05.2015 6:08:12	imap.gmail.com	Rx '. OK Success'
21.05.2015 6:08:12	imap.gmail.com	   email with 163 lines,  8769 chars received
21.05.2015 6:08:13	imap.gmail.com	Tx '. STORE 1 +FLAGS (\DELETED)'
21.05.2015 6:08:13	imap.gmail.com	Rx '* 1 FETCH (FLAGS (\Seen \Deleted))'
21.05.2015 6:08:13	imap.gmail.com	Rx '. OK Success'
21.05.2015 6:08:13	imap.gmail.com	Tx '. EXPUNGE'
21.05.2015 6:08:13	imap.gmail.com	Rx '* 1 EXPUNGE'
21.05.2015 6:08:13	imap.gmail.com	Rx '* 0 EXISTS'
21.05.2015 6:08:13	imap.gmail.com	Rx '. OK Success'
21.05.2015 6:08:13	imap.gmail.com	Tx '. LOGOUT'
21.05.2015 6:08:13	imap.gmail.com	Rx '* BYE LOGOUT Requested'
21.05.2015 6:08:13	imap.gmail.com	Rx '. OK 73 good day (Success)'
21.05.2015 6:08:13	imap.gmail.com	   Pop3MailClient Connection State Closed reached



P.S. Коды пока настолько неэстетично выглядят, что пока выкладывать не буду.
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38964811
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А вот допустим есть 4 письма (нумерация по id тек. сессии а не по uid):
1-2-3-4
В какой последовательности надо забирать, чтоб самое старое забрать первым?
с головы 1-2-3-4 ?
или с хвоста? 4-3-2-1 ?
Для pop3? Для imap?
Я беру 1-2-3-4 но возникли сомнения?

Antonariyна mail.ru, а там был то ли баг, то ли фича: команда, имеющая параметром значение , применялась к двум сообщениям, заданному и следующему. а если сообщение одно или последнее, то все ок. мэйлру вопрос о том, что за ерунда творится, проигнорировало. по факту IMAP мне не был нужен, я и забил на него совсем.
не подтверждаю
4 письма скачались и удалились:
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
. FETCH 1 RFC822
. STORE 1 +FLAGS (\DELETED)
. FETCH 2 RFC822
. STORE 2 +FLAGS (\DELETED)
. FETCH 3 RFC822
. STORE 3 +FLAGS (\DELETED)
. FETCH 4 RFC822
. STORE 4 +FLAGS (\DELETED)
. EXPUNGE
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38964839
carrotik
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дмитрий77А вот допустим есть 4 письма (нумерация по id тек. сессии а не по uid):
1-2-3-4
В какой последовательности надо забирать, чтоб самое старое забрать первым?
с головы 1-2-3-4 ?
или с хвоста? 4-3-2-1 ?
Для pop3? Для imap?
Я беру 1-2-3-4 но возникли сомнения?


.. я уже говорил, у IMAP-a есть команда SEARCH - там можно выбирать по разным параметрам,
вот тут
.. полагаться на сквозную нумерацию я бы не стал ...
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38964908
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
carrotikДмитрий77Я беру 1-2-3-4 но возникли сомнения?
полагаться на сквозную нумерацию я бы не стал ...
Да не, вроде правильно делаю.
авторMessage Sequence Number Message Attribute

A relative position from 1 to the number of messages in the mailbox.
This position MUST be ordered by ascending unique identifier . As
each new message is added, it is assigned a message sequence number
that is 1 higher than the number of messages in the mailbox before
that new message was added.


Unique Identifier (UID) Message Attribute

Unique identifiers
are assigned in a strictly ascending fashion in the mailbox ; as each
message is added to the mailbox it is assigned a higher UID than the
message(s) which were added previously.

проверил
1-2-3-4
5645-5646-5647-5648

т.е. порядок Sequence соответствует порядку Unique, и порядок этот возрастающий.
И в той же последовательности 1-2-3-4 скачивает pop3
1-самое старое 4 -самое новое
понятно что если пришли почти одновременно то могут чуть перепутаться с т.зр. времени их отправки и т.п. Но очередь получения сервером (добавления в папку) здесь соблюдена.
Что мне важно, чтобы при возникновении очереди новые "задания" не лезли сильно вперед "старых", обработаны они будут в той же последовательности что и скачаны.
Но на самом деле при интервале проверки писем 20 сек об этом можно вообще не заморачиваться.

Но рассчитывать можно. А search это сложности и излишки и еще непонятно чего она там насортирует в зависимости от фантазии вопрошающего.
...
Рейтинг: 0 / 0
А про IMAP не разжуете?
    #38965858
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, собственно конечный допиленный результат (полный код под спойлером внизу).
Тестировал с gmail.com, Hotmail.com, mail.ru (ssl,993) и с агавой по 143 порту.
Ошибок в работе не замечено (кроме того что gmail после удаления по IMAP оставляет письма в POP3, но только gmail).

Код: vbnet
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.
  Public Sub GetMailImap(ByVal m_ImapServer As String, ByVal m_User As String, ByVal m_Password As String, _
   Optional ByVal m_ServerPort As Integer = 143, Optional ByVal m_useSSL As Boolean = False, _
   Optional ByVal m_DeleteEmails As Boolean = True, Optional ByVal m_SaveDir As String = vbNullString, _
   Optional ByVal m_SaveMailPrefix As String = "MSG", Optional ByVal m_SaveMailExt As String = ".eml", _
   Optional ByVal m_TraceFunction As Imap.TraceHandler = Nothing, Optional ByVal m_TestMode As Boolean = False)

     Try
      ' prepare Imap client
      Dim ImapClient As Imap.cImapMailClient = _
       New Imap.cImapMailClient(m_ImapServer, m_ServerPort, m_useSSL, m_User, m_Password)
      ImapClient.IsAutoReconnect = True

      'if tracing needed
      If m_TraceFunction IsNot Nothing Then AddHandler ImapClient.Trace, m_TraceFunction

      ImapClient.ReadTimeout = 60000 'give Imap server 60 seconds to answer

      'establish connection
      ImapClient.Connect()

      'select inbox
      Dim NumberOfMails As Integer = 0
      If ImapClient.SelectMailbox("INBOX", NumberOfMails) Then

        If m_TestMode Then

          'only show info
          If NumberOfMails > 0 Then
            For i As Integer = 1 To NumberOfMails
              'get Unique Email Id
              Dim UniqueEmailId As Integer
              ImapClient.GetUniqueEmailId(i, UniqueEmailId)

              'get email size
              Dim EmailSize As Integer
              ImapClient.GetEmailSize(i, EmailSize)
            Next
          End If

          'ping server
          ImapClient.NOOP()

        Else

          'get emails
          If NumberOfMails > 0 Then

            If Strings.Len(m_SaveDir) = 0 OrElse IO.Directory.Exists(m_SaveDir) = False Then _
             m_SaveDir = My.Application.Info.DirectoryPath
            If Strings.Len(m_SaveMailPrefix) = 0 Then m_SaveMailPrefix = "MSG"
            If Strings.Len(m_SaveMailExt) = 0 Then m_SaveMailExt = ".eml"
            If Strings.Left(m_SaveMailExt, 1) <> "." Then m_SaveMailExt = "." & m_SaveMailExt

            For i As Integer = 1 To NumberOfMails

              'get email
              Dim Email As String = ""
              ImapClient.GetRawEmail(i, Email)
              If Strings.Len(Email) > 0 Then
                Dim fToSave As String = GetNextEmailFileName(m_SaveDir, m_SaveMailPrefix, m_SaveMailExt)
                Try : IO.File.WriteAllText(fToSave, Email, System.Text.Encoding.ASCII) : Catch : End Try
              End If

              'delete email
              If m_DeleteEmails Then ImapClient.DeleteEmail(i)
            Next
            If m_DeleteEmails Then ImapClient.Expunge()
          End If

        End If

      End If

      'close connection
      ImapClient.Disconnect()

    Catch ex As Exception
      If m_TraceFunction IsNot Nothing Then
        m_TraceFunction("Run Time Error Occured:")
        m_TraceFunction(ex.Message)
        m_TraceFunction(ex.StackTrace)
      End If
    End Try

  End Sub




Код: vbnet
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.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
472.
473.
474.
475.
476.
477.
478.
479.
480.
481.
482.
483.
484.
485.
486.
487.
488.
489.
490.
491.
492.
493.
494.
495.
496.
497.
498.
499.
500.
501.
502.
503.
504.
505.
506.
507.
508.
509.
510.
511.
512.
513.
514.
515.
516.
517.
518.
519.
520.
521.
522.
523.
524.
525.
526.
527.
528.
529.
530.
531.
532.
533.
534.
535.
536.
537.
538.
539.
540.
541.
542.
543.
544.
545.
546.
547.
548.
549.
550.
551.
552.
553.
554.
555.
556.
557.
558.
559.
560.
561.
562.
563.
564.
565.
566.
567.
568.
569.
570.
571.
572.
573.
574.
575.
576.
577.
578.
579.
580.
581.
582.
583.
584.
585.
586.
587.
588.
589.
590.
591.
592.
593.
594.
595.
596.
597.
598.
599.
600.
601.
602.
603.
604.
605.
606.
607.
608.
609.
610.
611.
612.
613.
614.
615.
616.
617.
618.
619.
620.
621.
622.
623.
624.
625.
626.
627.
628.
629.
630.
631.
632.
633.
634.
635.
636.
637.
638.
639.
640.
641.
642.
643.
644.
645.
646.
647.
648.
649.
650.
651.
652.
653.
654.
655.
656.
657.
658.
659.
660.
661.
662.
663.
664.
665.
666.
667.
668.
669.
670.
671.
672.
673.
674.
675.
676.
677.
678.
679.
680.
681.
682.
683.
684.
685.
686.
687.
688.
689.
690.
691.
692.
693.
694.
695.
696.
697.
698.
699.
700.
701.
702.
703.
704.
705.
706.
707.
708.
709.
710.
711.
712.
713.
714.
715.
716.
717.
718.
719.
720.
721.
722.
723.
724.
725.
726.
727.
728.
729.
730.
731.
732.
733.
734.
735.
736.
737.
738.
739.
740.
741.
742.
743.
744.
745.
746.
747.
748.
749.
750.
751.
752.
753.
754.
755.
756.
757.
758.
759.
760.
761.
762.
763.
764.
765.
766.
767.
768.
769.
770.
771.
772.
773.
774.
775.
776.
777.
778.
779.
780.
781.
782.
783.
784.
785.
786.
787.
788.
789.
790.
791.
792.
793.
794.
795.
796.
797.
798.
799.
800.
801.
802.
803.
804.
805.
806.
807.
808.
809.
810.
811.
812.
813.
814.
815.
816.
817.
818.
819.
820.
821.
822.
823.
824.
825.
826.
827.
828.
829.
830.
831.
832.
833.
834.
835.
836.
837.
838.
839.
840.
841.
842.
843.
844.
845.
846.
847.
848.
849.
850.
851.
852.
853.
854.
855.
856.
857.
858.
859.
860.
861.
862.
863.
864.
865.
866.
867.
868.
869.
870.
871.
872.
873.
874.
875.
876.
877.
878.
879.
880.
881.
882.
883.
884.
885.
886.
887.
888.
889.
890.
891.
892.
893.
894.
895.
896.
897.
898.
899.
Imports System.Net.Sockets
Imports System.Net.Security
Imports System.IO
Imports System.Text

Module ModuleImap

  Public Sub GetMailImap(ByVal m_ImapServer As String, ByVal m_User As String, ByVal m_Password As String, _
   Optional ByVal m_ServerPort As Integer = 143, Optional ByVal m_useSSL As Boolean = False, _
   Optional ByVal m_DeleteEmails As Boolean = True, Optional ByVal m_SaveDir As String = vbNullString, _
   Optional ByVal m_SaveMailPrefix As String = "MSG", Optional ByVal m_SaveMailExt As String = ".eml", _
   Optional ByVal m_TraceFunction As Imap.TraceHandler = Nothing, Optional ByVal m_TestMode As Boolean = False)

    If m_TraceFunction IsNot Nothing AndAlso m_TestMode = False Then m_TraceFunction("-------------------------")
    Try
      ' prepare Imap client
      Dim ImapClient As Imap.cImapMailClient = _
       New Imap.cImapMailClient(m_ImapServer, m_ServerPort, m_useSSL, m_User, m_Password)
      ImapClient.IsAutoReconnect = True

      'if tracing needed
      If m_TraceFunction IsNot Nothing Then AddHandler ImapClient.Trace, m_TraceFunction

      ImapClient.ReadTimeout = 60000 'give Imap server 60 seconds to answer

      'establish connection
      ImapClient.Connect()

      'select inbox
      Dim NumberOfMails As Integer = 0
      If ImapClient.SelectMailbox("INBOX", NumberOfMails) Then

        If m_TestMode Then

          'only show info
          If NumberOfMails > 0 Then
            For i As Integer = 1 To NumberOfMails
              'get Unique Email Id
              Dim UniqueEmailId As Integer
              ImapClient.GetUniqueEmailId(i, UniqueEmailId)

              'get email size
              Dim EmailSize As Integer
              ImapClient.GetEmailSize(i, EmailSize)
            Next
          End If

          'ping server
          ImapClient.NOOP()

        Else

          'get emails
          If NumberOfMails > 0 Then

            If Strings.Len(m_SaveDir) = 0 OrElse IO.Directory.Exists(m_SaveDir) = False Then _
             m_SaveDir = My.Application.Info.DirectoryPath
            If Strings.Len(m_SaveMailPrefix) = 0 Then m_SaveMailPrefix = "MSG"
            If Strings.Len(m_SaveMailExt) = 0 Then m_SaveMailExt = ".eml"
            If Strings.Left(m_SaveMailExt, 1) <> "." Then m_SaveMailExt = "." & m_SaveMailExt

            For i As Integer = 1 To NumberOfMails

              '===не надо этого здесь, это время, сравнимое со скачиванием!!! ===
              ''get Unique Email Id
              'Dim UniqueEmailId As Integer
              'ImapClient.GetUniqueEmailId(i, UniqueEmailId)

              ''get email size
              'Dim EmailSize As Integer
              'ImapClient.GetEmailSize(i, EmailSize)
              '===не надо этого здесь, это время!!! ===

              'get email
              Dim Email As String = ""
              ImapClient.GetRawEmail(i, Email)
              If Strings.Len(Email) > 0 Then
                Dim fToSave As String = GetNextEmailFileName(m_SaveDir, m_SaveMailPrefix, m_SaveMailExt)
                Try : IO.File.WriteAllText(fToSave, Email, System.Text.Encoding.ASCII) : Catch : End Try
              End If

              'delete email
              If m_DeleteEmails Then ImapClient.DeleteEmail(i)
            Next
            If m_DeleteEmails Then ImapClient.Expunge()
          End If

        End If

      End If

      'close connection
      ImapClient.Disconnect()

    Catch ex As Exception
      If m_TraceFunction IsNot Nothing Then
        m_TraceFunction("Run Time Error Occured:")
        m_TraceFunction(ex.Message)
        m_TraceFunction(ex.StackTrace)
      End If
    End Try
    If m_TraceFunction IsNot Nothing AndAlso m_TestMode = False Then m_TraceFunction("-------------------------")

  End Sub

  Private Function GetNextEmailFileName(ByVal path As String, ByVal pref As String, ByVal ext As String) As String
    Dim tmp_name As String
    Dim i As Integer = 0
    Do
      i = i + 1
      tmp_name = IO.Path.Combine(path, pref & i.ToString & ext)
      If IO.File.Exists(tmp_name) = False Then Return tmp_name
    Loop
  End Function

End Module

Namespace Imap
  ' Supporting classes and structs
  ' ==============================

  ''' <summary>
  ''' Combines Email ID with Email UID for one email
  ''' The Imap server assigns to each message a unique Email UID, which will not change for the life time
  ''' of the message and no other message should use the same.
  ''' 
  ''' Exceptions:
  ''' Throws ImapException if there is a serious communication problem with the Imap server, otherwise
  ''' 
  ''' </summary>
  Public Structure EmailUid
    ''' <summary>
    ''' used in IMAP commands to indicate which message (only valid in the present session)
    ''' </summary>
    Public EmailId As Integer
    ''' <summary>
    ''' Uid is always the same for a message, regardless of session
    ''' </summary>
    Public Uid As String

    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="EmailId"></param>
    ''' <param name="Uid"></param>
    Public Sub New(ByVal EmailId As Integer, ByVal Uid As String)
      Me.EmailId = EmailId
      Me.Uid = Uid
    End Sub
  End Structure

  ''' <summary>
  ''' If anything goes wrong within ImapMailClient, an ImapException is raised
  ''' </summary>
  Public Class ImapException
    Inherits ApplicationException
    ''' <summary>
    ''' 
    ''' </summary>
    Public Sub New()
    End Sub
    ''' <summary>
    ''' 
    ''' </summary>
    ''' <param name="ErrorMessage"></param>
    Public Sub New(ByVal ErrorMessage As String)
      MyBase.New(ErrorMessage)
    End Sub
  End Class

  ''' <summary>
  ''' An Imap connection goes through the following states:
  ''' </summary>
  Public Enum ImapConnectionStateEnum
    ''' <summary>
    ''' undefined
    ''' </summary>
    None = 0
    ''' <summary>
    ''' not connected yet to Imap server
    ''' </summary>
    Disconnected
    ''' <summary>
    ''' TCP connection has been opened and the Imap server has sent the greeting. Imap server expects user name and password
    ''' </summary>
    Authorization
    ''' <summary>
    ''' client has identified itself successfully with the IMAP, server has locked all messages 
    ''' </summary>
    Connected
    ''' <summary>
    ''' LOGOUT command was sent, the server has released the resources
    ''' </summary>
    Closed
  End Enum

  ' Delegates for ImapMailClient
  ' ============================

  ''' <summary>
  ''' If IMAP Server doesn't react as expected or this code has a problem, but
  ''' can continue with the execution, a Warning is called.
  ''' </summary>
  ''' <param name="WarningText"></param>
  ''' <param name="Response">string received from IMAP server</param>
  Public Delegate Sub WarningHandler(ByVal WarningText As String, ByVal Response As String)

  ''' <summary>
  ''' Traces all the information exchanged between IMAP client and IMAP server plus some
  ''' status messages from IMAP client.
  ''' Helpful to investigate any problem.
  ''' Console.WriteLine() can be used
  ''' </summary>
  ''' <param name="TraceText"></param>
  Public Delegate Sub TraceHandler(ByVal TraceText As String)

  ' cImapMailClient
  ' ====================  

  ''' <summary>
  ''' provides access to emails on an IMAP Server
  ''' </summary>
  Public Class cImapMailClient

    'Events
    '------

    ''' <summary>
    ''' Called whenever IMAP server doesn't react as expected, but no runtime error is thrown.
    ''' </summary>
    Public Event Warning As WarningHandler

    ''' <summary>
    ''' call warning event
    ''' </summary>
    ''' <param name="methodName">name of the method where warning is needed</param>
    ''' <param name="response">answer from IMAP server causing the warning</param>
    ''' <param name="warningText">explanation what went wrong</param>
    ''' <param name="warningParameters"></param>
    Protected Sub CallWarning(ByVal methodName As String, ByVal response As String, _
     ByVal warningText As String, ByVal ParamArray warningParameters As Object())
      warningText = String.Format(warningText, warningParameters)
      RaiseEvent Warning(Convert.ToString(methodName & Convert.ToString(": ")) & warningText, response)
      CallTrace("!! {0}", warningText)
    End Sub

    ''' <summary>
    ''' Shows the communication between ImapClient and ImapServer, including warnings
    ''' </summary>
    Public Event Trace As TraceHandler

    ''' <summary>
    ''' call Trace event
    ''' </summary>
    ''' <param name="text">string to be traced</param>
    ''' <param name="parameters"></param>
    Protected Sub CallTrace(ByVal text As String, ByVal ParamArray parameters As Object())
      'RaiseEvent Trace(DateTime.Now.ToString("hh:mm:ss ") + m_ImapServer + " " + String.Format(text, parameters))
      RaiseEvent Trace(DateTime.Now.ToString + Chr(9) + m_ImapServer + Chr(9) + String.Format(text, parameters))
    End Sub

    ''' <summary>
    ''' Trace information received from IMAP server
    ''' </summary>
    ''' <param name="text">string to be traced</param>
    ''' <param name="parameters"></param>
    Protected Sub TraceFrom(ByVal text As String, ByVal ParamArray parameters As Object())
      CallTrace("   " + String.Format(text, parameters))
    End Sub

    'Properties
    '------

    ''' <summary>
    ''' Get IMAP server name
    ''' </summary>
    Public ReadOnly Property ImapServer() As String
      Get
        Return m_ImapServer
      End Get
    End Property
    ''' <summary>
    ''' IMAP server name
    ''' </summary>
    Protected m_ImapServer As String

    ''' <summary>
    ''' Get IMAP server port
    ''' </summary>
    Public ReadOnly Property Port() As Integer
      Get
        Return m_port
      End Get
    End Property
    ''' <summary>
    ''' POP3 server port
    ''' </summary>
    Protected m_port As Integer

    ''' <summary>
    ''' Should SSL be used for connection with IMAP server ?
    ''' </summary>
    Public ReadOnly Property UseSSL() As Boolean
      Get
        Return m_useSSL
      End Get
    End Property
    ''' <summary>
    ''' Should SSL be used for connection with IMAP server ?
    ''' </summary>
    Private m_useSSL As Boolean

    ''' <summary>
    ''' should ImapMailClient automatically reconnect if IMAP server has dropped the 
    ''' connection due to a timeout ?
    ''' </summary>
    Public Property IsAutoReconnect() As Boolean
      Get
        Return m_isAutoReconnect
      End Get
      Set(ByVal value As Boolean)
        m_isAutoReconnect = value
      End Set
    End Property
    Private m_isAutoReconnect As Boolean = False
    'timeout has occured, we try to perform an autoreconnect
    Private isTimeoutReconnect As Boolean = False

    ''' <summary>
    ''' Get / set read timeout (miliseconds)
    ''' </summary>
    Public Property ReadTimeout() As Integer
      Get
        Return m_readTimeout
      End Get
      Set(ByVal value As Integer)
        m_readTimeout = value
        If ImapStream IsNot Nothing AndAlso ImapStream.CanTimeout Then
          ImapStream.ReadTimeout = m_readTimeout
        End If
      End Set
    End Property
    ''' <summary>
    ''' IMAP server read timeout
    ''' </summary>
    Protected m_readTimeout As Integer = -1

    ''' <summary>
    ''' Get owner name of mailbox on IMAP server
    ''' </summary>
    Public ReadOnly Property Username() As String
      Get
        Return m_username
      End Get
    End Property
    ''' <summary>
    ''' Owner name of mailbox on IMAP server
    ''' </summary>
    Protected m_username As String

    ''' <summary>
    ''' Get password for mailbox on IMAP server
    ''' </summary>
    Public ReadOnly Property Password() As String
      Get
        Return m_password
      End Get
    End Property
    ''' <summary>
    ''' Password for mailbox on IMAP server
    ''' </summary>
    Protected m_password As String

    ''' <summary>
    ''' Get connection status with IMAP server
    ''' </summary>
    Public ReadOnly Property ImapConnectionState() As ImapConnectionStateEnum
      Get
        Return m_ImapConnectionState
      End Get
    End Property
    ''' <summary>
    ''' connection status with IMAP server
    ''' </summary>
    Protected m_ImapConnectionState As ImapConnectionStateEnum = ImapConnectionStateEnum.Disconnected

    ' Methods
    ' -------

    ''' <summary>
    ''' set IMAP connection state
    ''' </summary>
    ''' <param name="State"></param>
    Protected Sub setImapConnectionState(ByVal State As ImapConnectionStateEnum)
      m_ImapConnectionState = State
      CallTrace("   ImapMailClient Connection State {0} reached", State)
    End Sub

    ''' <summary>
    ''' throw exception if IMAP connection is not in the required state
    ''' </summary>
    ''' <param name="requiredState"></param>
    Protected Sub EnsureState(ByVal requiredState As ImapConnectionStateEnum)
      If m_ImapConnectionState <> requiredState Then
        ' wrong connection state
        Throw New ImapException("This command only accepted during connection state: " + requiredState.ToString() + _
         vbLf & " The connection to server " + m_ImapServer + " is in state " + m_ImapConnectionState.ToString())
      End If
    End Sub

    'private fields
    '--------------
    ''' <summary>
    ''' TCP to IMAP server
    ''' </summary>
    Private serverTcpConnection As TcpClient
    ''' <summary>
    ''' Stream from IMAP server with or without SSL
    ''' </summary>
    Private ImapStream As Stream
    ''' <summary>
    ''' Reader for IMAP message
    ''' </summary>
    Protected ImapStreamReader As StreamReader
    ''' <summary>
    ''' char 'array' for carriage return / line feed
    ''' </summary>
    Protected CRLF As String = vbCr & vbLf

    'public methods
    '--------------

    ''' <summary>
    ''' Make IMAP client ready to connect to IMAP server
    ''' </summary>
    ''' <param name="ImapServer"><example>imap.gmail.com</example></param>
    ''' <param name="Port"><example>993</example></param>
    ''' <param name="useSSL">True: SSL is used for connection to IMAP server</param>
    ''' <param name="Username"><example>abc@gmail.com<;/example></param>
    ''' <param name="Password">Secret</param>
    Public Sub New(ByVal ImapServer As String, ByVal Port As Integer, ByVal useSSL As Boolean, _
     ByVal Username As String, ByVal Password As String)
      Me.m_ImapServer = ImapServer
      Me.m_port = Port
      Me.m_useSSL = useSSL
      Me.m_username = Username
      Me.m_password = Password
    End Sub

    ''' <summary>
    ''' Connect to IMAP server
    ''' </summary>
    Public Sub Connect()
      If (m_ImapConnectionState <> ImapConnectionStateEnum.Disconnected) AndAlso
       (m_ImapConnectionState <> ImapConnectionStateEnum.Closed) AndAlso
       (Not isTimeoutReconnect) Then
        CallWarning("connect", "", "Connect command received, but connection state is: " + m_ImapConnectionState.ToString())
      Else
        'establish TCP connection
        Try
          CallTrace("   Connect at port {0}", m_port)
          serverTcpConnection = New TcpClient(m_ImapServer, m_port)
        Catch ex As Exception
          Throw New ImapException("Connection to server " + m_ImapServer + ", port " + m_port.ToString + " failed." & vbCrLf & "Runtime Error: " + ex.ToString())
        End Try

        If m_useSSL Then
          'get SSL stream
          Try
            CallTrace("   Get SSL connection")
            ImapStream = New SslStream(serverTcpConnection.GetStream(), False)
            ImapStream.ReadTimeout = m_readTimeout
          Catch ex As Exception
            Throw New ImapException("Server " + m_ImapServer + " found, but cannot get SSL data stream." & vbCrLf & "Runtime Error: " + ex.ToString())
          End Try

          'perform SSL authentication
          Try
            CallTrace("   Get SSL authentication")
            DirectCast(ImapStream, SslStream).AuthenticateAsClient(m_ImapServer)
          Catch ex As Exception
            Throw New ImapException("Server " + m_ImapServer + " found, but problem with SSL Authentication." & vbCrLf & "Runtime Error: " + ex.ToString())
          End Try
        Else
          'create a stream to IMAP server without using SSL
          Try
            CallTrace("   Get connection without SSL")
            ImapStream = serverTcpConnection.GetStream()
            ImapStream.ReadTimeout = m_readTimeout
          Catch ex As Exception
            Throw New ImapException("Server " + m_ImapServer + " found, but cannot get data stream (without SSL)." & vbCrLf & "Runtime Error: " + ex.ToString())
          End Try
        End If

        'get stream for reading from pop server
        'POP3 allows only US-ASCII. The message will be translated in the proper encoding in a later step
        Try
          ImapStreamReader = New StreamReader(ImapStream, Encoding.ASCII)
        Catch ex As Exception
          If m_useSSL Then
            Throw New ImapException("Server " + m_ImapServer + " found, but cannot read from SSL stream." & vbCrLf & "Runtime Error: " + ex.ToString())
          Else
            Throw New ImapException("Server " + m_ImapServer + " found, but cannot read from stream (without SSL)." & vbCrLf & "Runtime Error: " + ex.ToString())
          End If
        End Try

        'ready for authorisation
        Dim response As String = ""
        If Not readSingleLine(response) Then
          Throw New ImapException(Convert.ToString("Server " + m_ImapServer + " not ready to start AUTHORIZATION." & vbCrLf & "Message: ") & response)
        End If
        setImapConnectionState(ImapConnectionStateEnum.Authorization)

        'send user name
        If Not executeCommand("LOGIN " + m_username + " " + m_password, response) Then
          Throw New ImapException(Convert.ToString("Server " + m_ImapServer + " doesn't accept username '" + m_username + "' and password '" + m_password + "'." & vbCrLf & "Message: ") & response)
        End If

        setImapConnectionState(ImapConnectionStateEnum.Connected)
      End If
    End Sub

    ''' <summary>
    ''' Disconnect from IMAP Server
    ''' </summary>
    Public Sub Disconnect()
      If m_ImapConnectionState = ImapConnectionStateEnum.Disconnected OrElse _
       m_ImapConnectionState = ImapConnectionStateEnum.Closed Then
        CallWarning("disconnect", "", "Disconnect received, but was already disconnected.")
      Else
        'ask server to end session and possibly to remove emails marked for deletion
        Try
          Dim response As String = ""
          If executeCommand("LOGOUT", response) Then
            'server says everything is ok
            setImapConnectionState(ImapConnectionStateEnum.Closed)
          Else
            'server says there is a problem
            CallWarning("Disconnect", response, Convert.ToString("negative response from server while closing connection: ") & response)
            setImapConnectionState(ImapConnectionStateEnum.Disconnected)
          End If
        Finally
          'close connection
          If ImapStream IsNot Nothing Then
            ImapStream.Close()
          End If

          ImapStreamReader.Close()
        End Try
      End If
    End Sub

    ''' <summary>
    ''' Selects a mailbox so that messages in the mailbox can be accessed
    ''' </summary>
    ''' <param name="MailboxFolder">mailbox name, usually INBOX</param>
    ''' <param name="NumberOfMails">Return the number of messages in the mailbox</param>
    ''' <returns></returns>
    Public Function SelectMailbox(ByVal MailboxFolder As String, ByRef NumberOfMails As Integer) As Boolean
      EnsureState(ImapConnectionStateEnum.Connected)

      'read response from server
      Dim response As String = ""
      Dim responses As New Collection 'все строки, а не только крайняя которая с тагом
      If Not executeCommand("SELECT " & MailboxFolder, response, , responses) Then
        CallWarning("SelectMailbox", response, "failed to select " & MailboxFolder & " folder")
        Return False
      End If
      For Each s As String In responses
        If (s.Length > 0) AndAlso s(0) = "*"c Then
          If InStr(UCase(s), "EXISTS") > 0 Then
            ' Rx '* 0 EXISTS'
            NumberOfMails = CType(Val(Split(s, "*")(1)), Integer)
            Exit For
          End If
        End If
      Next
      Return True
    End Function

    ''' <summary>
    ''' Delete message from server.
    ''' Flag is set on the message marking it as deleted. This, by itself, 
    ''' does nothing to get the message removed. Just when a special 
    ''' command is called all messages in the current folder marked 
    ''' as to be deleted are removed.
    ''' </summary>
    ''' <param name="msg_number"></param>
    ''' <returns></returns>
    Public Function DeleteEmail(ByVal msg_number As Integer) As Boolean
      EnsureState(ImapConnectionStateEnum.Connected)
      Dim response As String = ""
      If Not executeCommand("STORE " + msg_number.ToString() + " +FLAGS (\DELETED)", response) Then
        CallWarning("DeleteEmail", response, "negative response for email (Id: {0}) delete request", msg_number)
        Return False
      End If
      Return True
    End Function

    ''' <summary>
    ''' The EXPUNGE command permanently removes all messages that have the
    ''' \Deleted flag set from the currently selected mailbox. Before
    ''' returning an OK to the client, an untagged EXPUNGE response is
    ''' sent for each message that is removed.
    ''' </summary>
    ''' <returns></returns>
    Public Function Expunge() As Boolean
      EnsureState(ImapConnectionStateEnum.Connected)
      Dim response As String = ""
      Return executeCommand("EXPUNGE", response)
    End Function

    ''' <summary>
    ''' get size of one particular email
    ''' </summary>
    ''' <param name="msg_number"></param>
    ''' <param name="EmailSize"></param>
    ''' <returns></returns>
    Public Function GetEmailSize(ByVal msg_number As Integer, ByRef EmailSize As Integer) As Boolean
      EnsureState(ImapConnectionStateEnum.Connected)
      Dim response As String = ""
      Dim responses As New Collection
      If executeCommand("FETCH " + msg_number.ToString() + " RFC822.SIZE", response, , responses) = False Then Return False

      For Each s As String In responses
        If (s.Length > 0) AndAlso (s(0) = "*"c) Then
          If InStr(UCase(s), "FETCH") > 0 AndAlso InStr(UCase(s), "RFC822.SIZE") > 0 _
           AndAlso InStr(s, "(") > 0 AndAlso InStr(s, ")") > 0 Then
            'Rx '* 1 FETCH (RFC822.SIZE 43534)'
            EmailSize = CType(Val(Strings.Right(s, Strings.Len(s) - InStr(UCase(s), "RFC822.SIZE") - 10)), Integer)
            Return True
          End If
        End If
      Next
      Return False
    End Function

    ''' <summary>
    ''' get Unique Email Id
    ''' </summary>
    ''' <param name="msg_number"></param>
    ''' <param name="UniqueEmailId"></param>
    ''' <returns></returns>
    Public Function GetUniqueEmailId(ByVal msg_number As Integer, ByRef UniqueEmailId As Integer) As Boolean
      EnsureState(ImapConnectionStateEnum.Connected)
      Dim response As String = ""
      Dim responses As New Collection
      If executeCommand("FETCH " + msg_number.ToString() + " UID", response, , responses) = False Then Return False

      For Each s As String In responses
        If (s.Length > 0) AndAlso (s(0) = "*"c) Then
          If InStr(UCase(s), "FETCH") > 0 AndAlso InStr(UCase(s), "UID") > 0 _
           AndAlso InStr(s, "(") > 0 AndAlso InStr(s, ")") > 0 Then
            'Rx '* 1 FETCH (UID 5449)'
            UniqueEmailId = CType(Val(Strings.Right(s, Strings.Len(s) - InStr(UCase(s), "UID") - 2)), Integer)
            Return True
          End If
        End If
      Next
      Return False
    End Function

    ''' <summary>
    ''' Sends an 'empty' command to the IMAP server. Server has to respond with OK
    ''' </summary>
    ''' <returns>true: server responds as expected</returns>
    Public Function NOOP() As Boolean
      EnsureState(ImapConnectionStateEnum.Connected)
      Dim response As String = ""
      If Not executeCommand("NOOP", response) Then
        CallWarning("NOOP", response, "negative response for NOOP request")
        Return False
      End If
      Return True
    End Function

    ''' <summary>
    ''' Should the raw content, the US-ASCII code as received, be traced
    ''' GetRawEmail will switch it on when it starts and off once finished
    ''' 
    ''' Inheritors might use it to get the raw email
    ''' </summary>
    Protected isTraceRawEmail As Boolean = False


    ''' <summary>
    ''' contains one MIME part of the email in US-ASCII, needs to be translated in .NET string (Unicode)
    ''' contains the complete email in US-ASCII, needs to be translated in .NET string (Unicode)
    ''' For speed reasons, reuse StringBuilder
    ''' </summary>
    Protected RawEmailSB As StringBuilder

    ''' <summary>
    ''' Reads the complete text of a message
    ''' </summary>
    ''' <param name="MessageNo">Email to retrieve</param>
    ''' <param name="EmailText">ASCII string of complete message</param>
    ''' <returns></returns>
    Public Function GetRawEmail(ByVal MessageNo As Integer, ByRef EmailText As String) As Boolean
      'send 'FETCH int RFC822' command to server
      EnsureState(ImapConnectionStateEnum.Connected)

      'read response from server
      Dim response As String = ""
      Dim responses As New Collection 'все строки, а не только крайняя которая с тагом
      ' retrieve mail with message number
      If Not executeCommand("FETCH " + MessageNo.ToString() + " RFC822", response, , responses) Then
        CallWarning("GetRawEmail", response, "failed to retrieve mail with message number " & MessageNo.ToString())
        Return False
      End If

      Dim elenth As Integer 'длина e-mail

      'get the lines
      Dim LineCounter As Integer = 0
      'empty StringBuilder
      If RawEmailSB Is Nothing Then
        RawEmailSB = New StringBuilder(100000)
      Else
        RawEmailSB.Length = 0
      End If
      Dim ReadRawEmail As Boolean = False
      For Each raw As String In responses
        If ReadRawEmail Then
          If raw.Length > 0 AndAlso raw(0) = "."c Then 'it is the last line
            EmailText = Strings.Left(RawEmailSB.ToString(), elenth) 'обрезаем сообщенным количеством символов
            TraceFrom("email with {0} lines,  {1} chars received", LineCounter.ToString(), EmailText.Length)
            Return True
          Else
            'collect all responses as received
            RawEmailSB.Append(raw & CRLF)
            LineCounter += 1
          End If
        Else
          If (raw.Length > 0) AndAlso (raw(0) = "*"c) Then
            If InStr(UCase(raw), "FETCH") > 0 AndAlso InStr(UCase(raw), "RFC822") > 0 _
             AndAlso InStr(raw, "{") > 0 AndAlso InStr(raw, "}") > 0 Then
              'Rx '* 1 FETCH (RFC822 {8769}'
              elenth = CType(Val(Split(Split(raw, "{")(1), "}")(0)), Integer)
              ReadRawEmail = True
            End If
          End If
        End If
      Next
      Return False
    End Function

    'Helper methodes
    '---------------

    Public isDebug As Boolean = False

    ''' <summary>
    ''' sends the command to IMAP server (adds CRLF) and waits for the
    ''' response of the server
    ''' </summary>
    ''' <param name="command">command to be sent to server</param>
    ''' <param name="response">final tagged answer from server</param>
    ''' <param name="tag">tag chosen by the client </param>
    ''' <param name="responses">collection of all answers from server</param>
    ''' <returns>false: server sent negative acknowledge, i.e. server could not execute command</returns>
    Private Function executeCommand(ByVal command As String, ByRef response As String, _
     Optional ByVal tag As String = ".", Optional ByRef responses As Collection = Nothing) As Boolean
      If Strings.Len(tag) = 0 Then tag = "."
      'send command to server
      Dim commandBytes As Byte() = System.Text.Encoding.ASCII.GetBytes((tag & " " & command & CRLF).ToCharArray())
      CallTrace("Tx '{0}'", tag & " " & command)
      Dim isSupressThrow As Boolean = False
      Try
        ImapStream.Write(commandBytes, 0, commandBytes.Length)
        If isDebug Then
          isDebug = False
          Throw New IOException("Test", New SocketException(10053))
        End If
      Catch ex As IOException
        'Unable to write data to the transport connection. Check if reconnection should be tried
        isSupressThrow = executeReconnect(ex, command, commandBytes, tag)
        If Not isSupressThrow Then
          Throw
        End If
      End Try
      ImapStream.Flush()

      'read response from server
      response = Nothing
      Do
        Try
          response = ImapStreamReader.ReadLine()
        Catch ex As IOException
          'Unable to write data to the transport connection. Check if reconnection should be tried
          isSupressThrow = executeReconnect(ex, command, commandBytes, tag)
          If isSupressThrow Then
            'wait for response one more time
            response = ImapStreamReader.ReadLine()
          Else
            Throw
          End If
        End Try
        If response Is Nothing Then
          Throw New ImapException("Server " + m_ImapServer + " has not responded, timeout has occured.")
        End If
        If responses IsNot Nothing Then responses.Add(response)
        If Strings.Left(response, 2) = "* " Then 'фактически все ответы приходят со * 
          CallTrace("Rx '{0}'", response) '(если без * ,данные мыла, то не надо это все выводить)
        ElseIf Strings.Left(response, Strings.Len(tag) + 1) = tag & " " Then 'или с тагом
          CallTrace("Rx '{0}'", response)
          Exit Do
        End If
      Loop
      Return Mid(response, InStr(response, " ") + 1, 2) = "OK"
    End Function

    ''' <summary>
    ''' reconnect, if there is a timeout exception and isAutoReconnect is true
    ''' 
    ''' </summary>
    Private Function executeReconnect(ByVal ex As IOException, ByVal command As String, _
     ByVal commandBytes As Byte(), Optional ByVal tag As String = ".") As Boolean
      If Strings.Len(tag) = 0 Then tag = "."
      If ex.InnerException IsNot Nothing AndAlso TypeOf ex.InnerException Is SocketException Then
        'SocketException
        Dim innerEx As SocketException = DirectCast(ex.InnerException, SocketException)
        If innerEx.ErrorCode = 10053 Then
          'probably timeout: An established connection was aborted by the software in your host machine.
          CallWarning("ExecuteCommand", "", "probably timeout occured")
          If m_isAutoReconnect Then
            'try to reconnect and send one more time
            isTimeoutReconnect = True
            Try
              CallTrace("   try to auto reconnect")
              Connect()

              CallTrace("   reconnect successful, try to resend command")
              CallTrace("Tx '{0}'", tag & " " & command)
              ImapStream.Write(commandBytes, 0, commandBytes.Length)
              ImapStream.Flush()
              Return True
            Finally
              isTimeoutReconnect = False
            End Try

          End If
        End If
      End If
      Return False
    End Function

    ''' <summary>
    ''' read single line response from IMAP server. 
    ''' <example>Example server response: *OK asdfkjahsf</example>
    ''' </summary>
    ''' <param name="response">response from IMAP server</param>
    ''' <returns>true: positive response</returns>
    Protected Function readSingleLine(ByRef response As String) As Boolean
      response = Nothing
      Try
        response = ImapStreamReader.ReadLine()
      Catch ex As Exception
        Dim s As String = ex.Message
      End Try
      If response Is Nothing Then
        Throw New ImapException("Server " + m_ImapServer + " has not responded, timeout has occured.")
      End If
      CallTrace("Rx '{0}'", response)
      Return (response.Length > 0 AndAlso response(0) = "*"c)
    End Function

    ' ''' <summary>
    ' ''' read one line in multiline mode from the IMAP server. 
    ' ''' </summary>
    ' ''' <param name="response">line received</param>
    ' ''' <returns>false: end of message</returns>
    'Protected Function readMultiLine(ByRef response As String) As Boolean
    '  response = Nothing
    '  response = ImapStreamReader.ReadLine()
    '  If response Is Nothing Then
    '    Throw New ImapException("Server " + m_ImapServer + " has not responded, probably timeout has occured.")
    '  End If
    '  If isTraceRawEmail Then
    '    'collect all responses as received
    '    RawEmailSB.Append(response & CRLF)
    '  End If
    '  'check for byte stuffing, i.e. if a line starts with a '.', another '.' is added, unless
    '  'it is the last line
    '  If response.Length > 0 AndAlso response(0) = "."c Then
    '    If Mid(response, InStr(response, " ") + 1, 2) = "OK" Then
    '      CallTrace("Rx '{0}'", response)
    '      'closing line found
    '      Return False
    '    End If
    '    'remove the first '.'
    '    response = response.Substring(1, response.Length - 1)
    '  End If
    '  Return True
    'End Function

  End Class

End Namespace

...
Рейтинг: 0 / 0
40 сообщений из 40, показаны все 2 страниц
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / А про IMAP не разжуете?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]