powered by simpleCommunicator - 2.0.53     © 2025 Programmizd 02
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Помогите решить проблему с сохранением аттачмент через CDO.
8 сообщений из 8, страница 1 из 1
Помогите решить проблему с сохранением аттачмент через CDO.
    #38162841
Дмитрий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.
Option Explicit
' Reference to Microsoft ActiveX Data Objects 2.5 Library
' Reference to Microsoft CDO for Windows 2000 Library

Public Type MsgInfo
  Sender As String
  Subject As String
  Body As String
  attach As String
End Type

Sub Main()
  MsgBox Command
  GetMsgInfoCDO Command
End Sub

Public Function GetMsgInfoCDO(MsgFile As String) As MsgInfo
    Dim att
    Dim str As String, strATT As String
    Dim mmm As CDO.Message
    strATT = ""
    Set mmm = LoadMessageFromFile(MsgFile)
    str = mmm.From
    If InStr(str, "<") > 0 Then 'нужен только e-mail
        str = Trim(Right(str, Len(str) - InStr(str, "<")))
        str = Trim(Left(str, InStr(str, ">") - 1))
    End If
    GetMsgInfoCDO.Sender = str
    GetMsgInfoCDO.Subject = mmm.Subject
    GetMsgInfoCDO.Body = mmm.TextBody
    MsgBox "sender=" & GetMsgInfoCDO.Sender & ";subject=" & _
     GetMsgInfoCDO.Subject & ";subject=" & GetMsgInfoCDO.Body
    For Each att In mmm.Attachments
        If Len(strATT) > 0 Then
            strATT = strATT & ";" & att.FileName
        Else
            strATT = att.FileName
        End If
        MsgBox "attach=" & Chr(34) & att.FileName & Chr(34) & " (len=" & Len(att.FileName) & ")"
        att.SaveToFile App.Path & "\" & att.FileName
        'только первое вложение пока
        'Exit For
    Next
    GetMsgInfoCDO.attach = strATT
End Function

Function LoadMessageFromFile(Path As String) As Message
    Dim Stm As New Stream
    Stm.Open
    Stm.LoadFromFile Path
    Dim iMsg As New CDO.Message
    Dim iDsrc As IDataSource
    Set iDsrc = iMsg
    iDsrc.OpenObject Stm, "_Stream"
    Set LoadMessageFromFile = iMsg
End Function



Клиент конечно намудрил но ошибка характерная:
Во вложении файл "Scan sa kopirke RUDOLF.eml"
И сдается что это все-таки не по хорватски а по англиски написано (перенастройка системы на Languages->Advanced-> Croatian во всяком случае не помогает).

А проблема такая:
Код
Код: vbnet
1.
2.
For Each att In mmm.Attachments
  strATT = att.FileName


возвращает пустую строку вместо имени аттачмента
а код
Код: vbnet
1.
att.SaveToFile App.Path & "\attach\" & att.FileName


соответственно вылетает с ошибкой
"The system can not find the file specified" (системе не удается найти путь)

В принципе на худой конец (нежелательно но можно) могу генерировать свое имя attachment-а
Но мне надо знать хотя б расширение аттачмента,
потому как далее по коду аттачмент отправляется на печать через printto а это depends on расширение файла (которое по смыслу приложения допустимо любое, но знать то надо)

Если не решается, то остается только отбрасывать такие письма со соей ошибкой "не возможно прочитать имя вложения", но не желательно опять же...

Подскажет кто? Желательно решение, кот. не зависит от языка в системе и языка в письме.
...
Рейтинг: 0 / 0
Помогите решить проблему с сохранением аттачмент через CDO.
    #38162992
скукотища
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Дмитрий77,
FRC 2046 , IANA .
Код: 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.
 
Public Function GetMsgInfoCDO(MsgFile As String) As MsgInfo
     
    {skipped}    

    Dim m2, at2
    For Each att In mmm.attachments
        Select Case att.ContentMediaType
        Case "message/rfc822"
          Set m2 = LoadMessageFromAttachment(att)
          
          ' вообще-то нужна рекурсивная обработка, - мало ли какую матрёшку пришлют :)
          For Each at2 In m2.attachments
                strATT = strATT & ";" & at2.Filename
                MsgBox "attach=" & Chr(34) & at2.Filename & Chr(34) & " (len=" & Len(at2.Filename) & ")"
                ' !! обработать случай, когда файл с таким именем уже существует
                at2.SaveToFile App.Path & "\" & at2.Filename
          Next at2
        
        Case "application/pdf", "image/tiff", "image/jpeg"
            strATT = strATT & ";" & att.Filename
            MsgBox "attach=" & Chr(34) & att.Filename & Chr(34) & " (len=" & Len(att.Filename) & ")"
            ' !! обработать случай, когда файл с таким именем уже существует
            att.SaveToFile App.Path & "\" & att.Filename
        
        Case Else
            ' do something
        End Select

        'только первое вложение пока
        'Exit For
    Next
    strATT = Mid$(strATT, 2)
    GetMsgInfoCDO.attach = strATT
End Function

' **********************************************************
Function LoadMessageFromAttachment(att) As Object
    Dim msg, iDS
    
    Set msg = CreateObject("cdo.message")
    Set iDS = msg.DataSource
    iDS.openobject att.GetDecodedContentStream, "_Stream"
    
    Set LoadMessageFromAttachment = msg
End Function

...
Рейтинг: 0 / 0
Помогите решить проблему с сохранением аттачмент через CDO.
    #38163141
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
скукотища,

спасибо, но боюсь ты не понял вопроса.
Я не ставлю целью разбор вложенных матрешек.
В оригинальном письме которое в коде проекта MSG1.eml
есть единственное вложение
- файл с именем "Scan sa kopirke RUDOLF.eml"
И CDO должно прочитать это имя
И все!!! (потом сохранить как файл "Scan sa kopirke RUDOLF.eml" по заданному пути)

strATT = att.FileName="Scan sa kopirke RUDOLF.eml"
Но не читает!!!

Я ради интереса отослал самому себе то же самое вложение (в своем письме).
Файл MSG2.eml прилагается
И в моем письме имя вложения читается (можете проверить с моим кодом).
...
Рейтинг: 0 / 0
Помогите решить проблему с сохранением аттачмент через CDO.
    #38163148
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И сдается мне, что единственный вариант,
если
att.FileName
возвращает пустую строку (по любой причине)
надо игнорировать данное вложение и не выполнять код сохранения вложения и добавления его имени к списку вложений:


Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
    For Each att In mmm.Attachments
      If Len(att.FileName) > 0 Then
        If Len(strATT) > 0 Then
            strATT = strATT & ";" & att.FileName
        Else
            strATT = att.FileName
        End If
        MsgBox "attach=" & Chr(34) & att.FileName & Chr(34) & " (len=" & Len(att.FileName) & ")"
        att.SaveToFile App.Path & "\" & att.FileName
      Else
        MsgBox "The attachment file name is unreadable!"
      End If
    Next
    GetMsgInfoCDO.attach = strATT



Ну, единственное когда клиенту отсылается письмо с ошибкой (когда нет вложений)
надо заменить фразу
"No attachments in your mail."
на что-нибудь типа
"No attachments in your mail or unreadable attachment name"
...
Рейтинг: 0 / 0
Помогите решить проблему с сохранением аттачмент через CDO.
    #38163202
скукотища
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
> Дмитрий77,
> спасибо, но боюсь ты не понял вопроса.
> Я не ставлю целью разбор вложенных матрешек.

Действительно не понял. Думал тебе нужны все файлы из вложений.


> В оригинальном письме которое в коде проекта MSG1.eml
> есть единственное вложение
> - файл с именем "Scan sa kopirke RUDOLF.eml"

В msg1.eml нет файла с именем "Scan sa kopirke RUDOLF.eml", - есть прикреплёное письмо c темой "Scan sa kopirke RUDOLF".
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
Content-Type: message/rfc822
Content-Disposition: attachment;
	creation-date="Fri, 22 Feb 2013 11:52:07 GMT";
	modification-date="Fri, 22 Feb 2013 11:52:07 GMT"
{Это пустая строка. после неё идёт само вложение}
Received: from rudolf.printer.kamgrad.hr (192.168.68.52) by
 anonymous-hermes.kamgrad.hr (192.168.68.15) with Microsoft SMTP Server id
 14.2.328.9; Fri, 22 Feb 2013 12:50:56 +0100
From: "rudolf@printer.kamgrad.hr" <rudolf@printer.kamgrad.hr>;
To: Vesna Kralj <Vesna.Kralj@kamgrad.hr>;
Subject: Scan sa kopirke RUDOLF
...


А вот в письме msg2.eml, которое ты сам себе отсылаешь уже есть файл "Scan sa kopirke RUDOLF.eml"
Код: vbnet
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Content-Type: application/octet-stream;
	name="Scan sa kopirke RUDOLF.eml"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="Scan sa kopirke RUDOLF.eml"
{Это пустая строка. после неё идёт само вложение}
Received: from rudolf.printer.kamgrad.hr (192.168.68.52) by
 anonymous-hermes.kamgrad.hr (192.168.68.15) with Microsoft SMTP Server =
id
 14.2.328.9; Fri, 22 Feb 2013 12:50:56 +0100
From: "rudolf@printer.kamgrad.hr" <rudolf@printer.kamgrad.hr>;
To: Vesna Kralj <Vesna.Kralj@kamgrad.hr>;
Subject: Scan sa kopirke RUDOLF
...




Как вариант, для сохранения аттачмента, как в варианте MSG1, можно читать тему письма, удалять из неё недопустимые для имени файла символы и сохранять ПИСЬМО в файл {преобразованнная тема}.eml
Код: 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.
  {skipped}
    Dim m2
    Dim filename$
    For Each att In mmm.attachments
        Select Case att.ContentMediaType
        Case "message/rfc822"
          Set m2 = LoadMessageFromAttachment(att)

          If Len(m2.Subject) > 0 Then
             filename = FileNameFromSubj(m2.Subject) & ".eml"
             MsgBox "attach=" & Chr(34) & filename & Chr(34) & " (len=" & Len(filename) & ")"
             ' !! обработать случай, когда файл с таким именем уже существует
             m2.getstream.SaveToFile App.Path & "\" & filename, 2
          Else
             ' пожаловаться, что нет аттачей, которые можно было бы сохранить
             ' или ... сохранить с именем 'HZXXXXX.eml' :)
          End If
        
        Case "application/pdf", "image/tiff", "image/jpeg"

  {skipped}

' **********************************************************
Function FileNameFromSubj$(ByVal Subj$)
    Const illegal$ = "\/:*?""<>|"
    Const dummy$ = "#"

    Dim s$, k&, i&
    
    For i = 1 To Len(illegal)
        s = Mid$(illegal, i, 1)
        k = InStr(1, Subj, s)
        If k > 0 Then Subj = Replace(Subj, s, dummy)
    Next i
    FileNameFromSubj = Subj
End Function

...
Рейтинг: 0 / 0
Помогите решить проблему с сохранением аттачмент через CDO.
    #38163231
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
скукотища,

>В msg1.eml нет файла с именем "Scan sa kopirke RUDOLF.eml",
> For Each att In mmm.attachments
> Case "message/rfc822"
> filename = FileNameFromSubj(m2.Subject) & ".eml"

Э, этак всех частных национально/(почтовый клиент что отсылал) зависимых случаев не переберешь
В коллекции mmm.attachments есть,
а имени при этом нет.
А ".eml" при этом от себя дописывается, а если это не .eml а .jpg и т.д.


Проще считать: нет имени - нет вложения.
По крайней мере это гарантирует "отсутствие crash", что гораздо важней.
...
Рейтинг: 0 / 0
Помогите решить проблему с сохранением аттачмент через CDO.
    #38163236
скукотища
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
> Дмитрий77,
> Э, этак всех частных национально/(почтовый клиент что отсылал) зависимых случаев не переберешь
> В коллекции mmm.attachments есть,
> а имени при этом нет.
> А ".eml" при этом от себя дописывается, а если это не .eml а .jpg и т.д.

Национально зависимые случаи перебирать и не надо. Ты информацию по ссылкам из 13969659 хоть по диагонали просмотрел ?

Расширение ".eml" я добавляю только для
Content-Type: message/rfc822

ЗЫ: Приложение твоё. Если считаешь, что достаточно обработывать только attachment.filename то так тому и быть.
...
Рейтинг: 0 / 0
Помогите решить проблему с сохранением аттачмент через CDO.
    #38163254
Дмитрий77
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
скукотищаЗЫ: Приложение твоё. Если считаешь, что достаточно обработывать только attachment.filename то так тому и быть.
Приложение
1) сохраняет вложения
2) пытается превратить их в TIFF используя метод "printto на виртуальный принтер", либо другой метод, если оговорен для конкретных типов вложений.
Поскольку "printto" сильно зависит от приложений в системе и настройки системы, то в общем случае допустимые типы attachment я и не ограничиваю.
В случае с ".eml" по задуманной логике система должна сохранить файл, а потом попытаться его распечатать.
А ошибка (обрабатываемая) возникла бы уже на этапе печати.
Но она возникла раньше (в чем и был вопрос).
В принципе думаю ДА, такие вложения проще вообще не обрабатывать никак.
...
Рейтинг: 0 / 0
8 сообщений из 8, страница 1 из 1
Форумы / Visual Basic [игнор отключен] [закрыт для гостей] / Помогите решить проблему с сохранением аттачмент через CDO.
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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