LINUX.ORG.RU

Отослать е-mail через lisp а именно cl-smtp и cl-mime


0

1

Здравствуйте, это не первая подобная тема но остальные все забросили хотя я и пишу туда вопросы. Проблема в том что никак не могу приатачить файл. У меня ща получается отправить письмо с любым телом письма, а ввести заголовок или добавить файл к письму не могу. Вот код, полностью весь со всеми библами.

(asdf:oos 'asdf:load-op :cl+ssl)
(asdf:oos 'asdf:load-op :cl-smtp)
(asdf:oos 'asdf:load-op :cl-mime)
(asdf:oos 'asdf:load-op :cl-BASE64)
(asdf:oos 'asdf:load-op :arnesi) 
(asdf:oos 'asdf:load-op :cl-prevalence)
(asdf:oos 'asdf:load-op :cl-gd)
  
(defun Отправить ()
	(with-open-file (поток-текста "C:/lisp/sbcl/Текст.txt")
		(setf Текст (read поток-текста)))
	(with-open-file (поток-рецепиентов "C:/lisp/sbcl/Рецепиенты.txt")
		(setf *Колличество-потоков* (read поток-рецепиентов))
		(loop for и from 1 upto *Колличество-потоков*
			do(send-email Текст(read поток-рецепиентов)))))

(defun send-email (text &rest reciepients)
  "Generic send SMTP mail with some TEXT to RECIEPIENTS"
  (cl-smtp:with-smtp-mail (out "хост"  "логин" reciepients :port 465 :authentication  (List "логин" "пароль") :local-hostname "логин")
    (cl-mime:print-mime out
	(make-instance
        'cl-mime:multipart-mime
        :subtype "mixed"
        :content (list
		(make-instance
                   'cl-mime:mime
                   :type "image"
                   :subtype (string-downcase (symbol-name (blob-type "E:\666.JPG")))
                   :encoding :base64
                   :content (flexi-streams:with-output-to-sequence (s)
                              (blob-to-stream "E:\666.JPG" s)))
		(make-instance 'cl-mime:mime
			:type "text"
            :encoding :base64
            :charset "UTF-8"
            :content (arnesi:string-to-octets text :utf-8))))
		#|(make-instance 'cl-mime:text-mime
            :encoding :base64
            :charset "UTF-8"
            :content (arnesi:string-to-octets text :utf-8))|#
      t t)))
и мне пишет ошибку что blob-type нет такого....тоесть не ошибка данных а именно типа нет такой функции или переменной.

вот статья по образу которой делал http://lisper.ru/articles/sendind-smtp-mail-with-utf-8-characters а это статья по образу которой пытался сделать приделать атач http://netzhansa.blogspot.com/2008/03/refactoring-cl-smtp.html

и мне пишет ошибку что blob-type нет такого....тоесть не ошибка данных а именно типа нет такой функции или переменной.

:subtype (string-downcase (symbol-name (blob-type "E:\666.JPG")))

А где функция blob-type определена? Ей префикс пакета не нужен?

Zubok ★★★★★ ()
Ответ на: комментарий от Zubok

так как взял из примера, то я просто не знаю в каком пакете. Поиск ничего не даёт. Вот я поэтому и пишу что возможно кто то расскажет... Кстати не обязательно картинку атачить если знаете как приатачить какой то другой документ то напишите пожалуйста.

RusNekromant ()
Ответ на: комментарий от RusNekromant

>так как взял из примера, то я просто не знаю в каком пакете.

Так а где пример с этой blob-type? Я по твоим ссылкам сходил, но там не обнаружил при беглом просмотре.

Zubok ★★★★★ ()

Насколько я понимаю, эта функция blob-type по файлу пытается определить его тип. В данном примере она должна возвратить 'jpeg. Потом 'jpeg преобразуется в «jpeg». И получается тип image/jpeg (:type: «image» :subtype «jpeg»).

Подставь тупо :subtype «jpeg» и проверь хотя бы работоспособность, а потом уже ищи откуда взялся этот автоопределятор типа файла.

P. S. С данными пакетами не работал ни разу. :)

Zubok ★★★★★ ()
Ответ на: комментарий от archimag

Да не статья хорошая но вот только плохо что автор насчёт атача не рассказал

RusNekromant ()
Ответ на: комментарий от RusNekromant

>Вторая ссылка, там есть я копировал оттуда, но там не показаны какие пакеты использованы.

Не нашел. Однако твоя blob-type определена в BKNR в bknr/base/data/blob.lisp

Zubok ★★★★★ ()

Пока у меня возникает ощущение, что ты не совсем понмиаешь, что ты делаешь. Ты выхватил пример из какого-то большого фреймфорка, а там уже используются его методы. Я пытаюсь просто угадать. Ты просто хочешь отправить почту, тогда тебе этот BKNR не нужен. Тебе надо прочитать инструкцию по cl-mime и определить, что надо передать с ключом :content (blob-to-stream — это тоже BKNR, т. е. тоже не найдет) и ключом :subtype (предполагаю, что строчку с подтипом MIME). вот и получи их любым известным тебе способом.

Zubok ★★★★★ ()
MimeMessage message = new MimeMessage();
messageBodyPart = new MimeBodyPart();
messageBodyPart.setDataHandler(new DataHandler(new FileDataSource("attachment.bin")));
message.setContent(multipart);
Transport.send(message);

Физкультпривет скобканутым. Пять строчек против ваших трёх десятков.

anonymous ()
Ответ на: комментарий от anonymous

> Пять строчек против ваших трёх десятков.

Многовато как-то. Да и делает этот код совсем не то.

archimag ★★★ ()

я пользовался cl-smtp:send-email
у нее есть keyword attachments
пример:

(send-email :to (list "Привет Чувак<test@mail.ru>")
            :subject "привет  привет     привет    привет   привет"
            :from "tester@tester.com"
            :display-name "Привет Чувак"
            :message "hello чувак"
            :attachments (list "/home/tester/logo.png"))

правда пришлось подмандить кодировку в библиотеке cl-smtp
чтобы работала с utf-8 в имени в адресе, теме и теле сообщения

но не смог добиться одинаковой работы при посылке на gmail и mail.ru
бросил и теперь делаю рассылку только на java

h1t ()
Ответ на: комментарий от anonymous

Вообще то у меня там не на один адрес шлёт, и плюс я новичёк наверняка можно урезать в два раза.

RusNekromant ()
Ответ на: комментарий от Zubok

Ну я знаю что должно получится, а вот как это сделать я не знаю)))) Инструкций к миму нет как раз в этом проблема никто мануала так и не написал. хотя может я просто не знаю где он лежит.... ладно спасибо за подсказку буду пробовать.

RusNekromant ()
Ответ на: комментарий от h1t

Мысль понял спасибо нада посмотреть где в макросе это дело находится.... А кодировка да.... Кстати а в чём разница между gmail и mail.ru я имею ввиду процес отправки сообщения? Вроде как стандартно всё работать должно по одним протоколам...

RusNekromant ()
Ответ на: комментарий от RusNekromant

>Ну я знаю что должно получится, а вот как это сделать я не знаю))))

Ну если точно знаешь, что ключи такие есть, то :content хочет sequence (flexi-streams:with-output-to-sequence (s) (blob-to-stream...)), а :subtype — точно строчку. Ты можешь попробовать для теста произвольную строчку или вектор в :content передать. :subtype «jpeg» :content «blah-blah-balh». Если все получится, что дальше ты можешь уже открывать свой реальный файл с картинкой и гнать его в sequence.

Zubok ★★★★★ ()
Ответ на: комментарий от Zubok

> (flexi-streams:with-output-to-sequence (s) (blob-to-stream...))

Это вообще через одно место, скорей всего можно сделать просто

(alexandria:read-file-into-byte-vector #P"/path/to/jpg")
archimag ★★★ ()
Ответ на: комментарий от Zubok

В :subtype можно всё что угодно прописать как я определил но поставил «jpeg» всё отправляется если в :content «C:\бла бла.jpeg» приходит письмо с двумя вложенными файлами в первом тип картинка... но она не открывается а во втором норм файлик текстовый который формируется вторым cl-mime:text-mime..... получается что сам он в контенте передаёт тупо название файла и внутрь пишет строку из того самого контента, он не открывает файл и не считывает.

А если прописать (flexi-streams:with-output-to-sequence (s) (blob-to-stream...)) то он говорит что blob-to-stream такого нет идентификатора и шлёт меня. Но вообще то преобразование в блоб должно быть обязательно если не ошибаюсь... вот только как

RusNekromant ()
Ответ на: комментарий от archimag

>Это вообще через одно место, скорей всего можно сделать просто

Это из примера ТС'а. Этот я привел как обоснование того, что :content — это последовательность.

Zubok ★★★★★ ()
Ответ на: комментарий от RusNekromant

>В :subtype можно всё что угодно прописать как я определил но поставил «jpeg» всё отправляется если в :content «C:\бла бла.jpeg» приходит письмо с двумя вложенными файлами в первом тип картинка... но она не открывается а во втором норм файлик текстовый который формируется вторым cl-mime:text-mime..... получается что сам он в контенте передаёт тупо название файла и внутрь пишет строку из того самого контента, он не открывает файл и не считывает.

Не совсем понимаю твою строчку «C:\бла бла.jpeg». Ты что, решил, что в качестве :content надо указать строчку с названием файла и у тебя этот файл уйдет атачментом? Гы-гы. Тебе надо файл прочитать и загнать его содержимое в sequence, а потом эту sequence загнать уже в :content.

И пришло у тебя все правильно. У тебя в качестве атачмента пришел файл с текстом «C:\бла бла.jpg». С чего ты взял, что он откроетс как картинка?

Zubok ★★★★★ ()
Ответ на: комментарий от Zubok

ну вот тут у «h1t»

[code=lisp](send-email :to (list «Привет Чувак<test@mail.ru>») :subject «привет привет привет привет привет» :from «tester@tester.com» :display-name «Привет Чувак» :message «hello чувак» :attachments (list «/home/tester/logo.png»))[/code]

показано что типа сам cl-smtp умеет читать я подумал что mime передаст smtp строку а сам smtp прочтёт и поставит, вот поэтому я и попробовал но понял что это не то... ща бум дальше эксперементировать.

RusNekromant ()
Ответ на: комментарий от RusNekromant

>показано что типа сам cl-smtp умеет читать я подумал что mime передаст smtp строку а сам smtp прочтёт и поставит, вот поэтому я и попробовал но понял что это не то... ща бум дальше эксперементировать.

Я не обратил сначала внимания. Выше показан пример с ключом :attachments у send-mail. Что туда передавать, я не знаю. Читай доку, смотри исходники. Вполне возможно, что cl-smtp умеет прикреплять файлы самостоятельно, но в примере не видно, как тип MIME указать. :) А cl-mime хочет не файл, а последовательность.

Zubok ★★★★★ ()
Ответ на: комментарий от Zubok

Всё разобрался всё работает пасибо и вам Zubok и archimag вот код который работает

(asdf:oos 'asdf:load-op :cl+ssl)
(asdf:oos 'asdf:load-op :cl-smtp)
(asdf:oos 'asdf:load-op :cl-mime)
(asdf:oos 'asdf:load-op :cl-BASE64)
(asdf:oos 'asdf:load-op :arnesi) 
(asdf:oos 'asdf:load-op :cl-prevalence)
  
(defun Отправить ()
	(with-open-file (поток-текста "C:/lisp/sbcl/Текст.txt")
		(setf Текст (read поток-текста)))
	(with-open-file (поток-рецепиентов "C:/lisp/sbcl/Рецепиенты.txt")
		(setf *Колличество-потоков* (read поток-рецепиентов))
		(loop for и from 1 upto *Колличество-потоков*
			do(send-email Текст(read поток-рецепиентов)))))

(defun send-email (text &rest reciepients)
  "Generic send SMTP mail with some TEXT to RECIEPIENTS"
  (cl-smtp:with-smtp-mail (out "хост"  "от кого" reciepients :port 465 :authentication  (List "логин" "пароль") :local-hostname "логин")
    (cl-mime:print-mime out
	(make-instance
        'cl-mime:multipart-mime
        :subtype "mixed"
        :content (list
		(make-instance
                   'cl-mime:mime
                   :type "application"
				   :subtype  "vnd.ms-excel"
                   ;:subtype (string-downcase (symbol-name (blob-type "E:\666.JPG")))
                   :encoding :base64
				   :content (alexandria:read-file-into-byte-vector #P"C:\\Агенства срезанные.xls"));"C:\Агенства срезанные.xls" )
				   ;:content (alexandria:read-file-into-byte-vector #P"E:\\666.JPG"));"C:\Агенства срезанные.xls" )
                   #|:content (flexi-streams:with-output-to-sequence (s)
                              (blob-to-stream "E:\666.JPG" s)))|#
		(make-instance 'cl-mime:text-mime
			;:type "text"
            :encoding :base64
            :charset "UTF-8"
            :content (arnesi:string-to-octets text :utf-8))))
      t t)))
Всё супер... правда тему пока указать не могу и тело пока не прописать но это всё фигня разберусь.... даже и без этого можно.... а вообще что бы приатачить файл нужно чётко указать тип :type и :subtype если их указать не правильно то файл всё равно придёт но без расширения и пользователю трудно будет понять чем открывать. узнать правильные «коды» типы можно из файла \cl-smtp\mime-types.lisp

так куча форматов вот такого вида

(«xls» «application/vnd.ms-excel» «MS Excel»)

из этой строки следует что тип application а под тип vnd.ms-excel наверное есть механизм автоопределения но я пока что не нашел, поэтому ручками ща делаю.

Так что всё готово.

RusNekromant ()
Ответ на: комментарий от RusNekromant

типы можно из файла \cl-smtp\mime-types.lisp
так куча форматов вот такого вида
(«xls» «application/vnd.ms-excel» «MS Excel»)

Может, тогда использовать этот :attachments в cl-smtp и не использовать cl-mime вообще?

Глянь файл README в cl-smtp:

------------------------------------------------
CLASS
cl-smtp:attachment 

 - accessor: attachment-name          : string 
 - accessor: attachment-data-pathname : pathname
 - accessor: attachment-mime-type     : string (mime-type)

It is now possible to send a file under a different name.
See cl-smtp:make-attachment.
------------------------------------------------

(cl-smtp:make-attachment data-pathname
			 &key (name (file-namestring data-pathname))
			      (mime-type (lookup-mime-type name)))

Create a instance of cl-smtp:attachment.

Returns cl-smtp:attachment

 arguments:
  - data-pathname                     : pathname
 keywords:
  - name                              : string, 
                                        default (file-namestring data-pathname)
  - mime-type                         : string,
                                        default (lookup-mime-type name)
------------------------------------------------
Zubok ★★★★★ ()
Ответ на: комментарий от Zubok

Ньдя всё оказалось проще... не понимаю зачем человек вообще макрос писал какой то в mime.... вот так всё отсылается

(cl-smtp:send-email "хост"  "от кого" "кому" "zagolovok" "soobshenie" :port 465 :authentication  (List "логин" "пароль"):attachments (list "C:\\Агенства срезанные.xls""E:\\666.JPG"))
немного криво выглядит но работает замечательно... осталось только в функцию обернуть и можно начинать. Преимущество в том что не нужно указывать тип, он определяется автоматически. Нет ограничений на колличество файлов, просто тупо добавляем в список и всё. Единственное что с русским языком не пробовал... но думаю эт можно решить перекодированием.... порт кстати тоже автоматом определяется но я привык всё указывать... хотя можно и не указывать.

RusNekromant ()
Ответ на: комментарий от RusNekromant

> немного криво выглядит

Ну, дык, отформатируй нормально:

(cl-smtp:send-email "хост"
                    "от кого"
                    "кому"
                    "zagolovok"
                    "soobshenie"
                    :port 465
                    :authentication '("логин" "пароль")
                    :attachments '("C:\\Агенства срезанные.xls" "E:\\666.JPG"))
archimag ★★★ ()
Ответ на: комментарий от archimag

Тогда стоит конечно или совсем убрать статью или поправить или указать что не актуальное решение....

RusNekromant ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.