Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/toyokumo/tarayo

:love_letter: SMTP client library for Clojure. That’s it.
https://github.com/toyokumo/tarayo

clojure smtp-client

Last synced: 7 days ago
JSON representation

:love_letter: SMTP client library for Clojure. That’s it.

Awesome Lists containing this project

README

        

= tarayo
:toc:
:toc-placement: preamble
:toclevels: 2

// Need some preamble to get TOC:
{empty}

SMTP client library for Clojure. That's it.

+++



Lint and Test


Codecov





+++

== Why tarayo?

Tarayo is heavily inspired by https://github.com/drewr/postal[drewr/postal].

* Only targets SMTP
** Provide only one feature.
** Use https://github.com/drewr/postal[drewr/postal] for `sendmail`.
* Explicit connection
** Handle the connection manually.
* Well tested

"Tarayo" is a tree name called "Tree of post office" in Japan.

== Usage

link:https://clojars.org/toyokumo/tarayo[image:https://img.shields.io/clojars/v/toyokumo/tarayo.svg[]]

[source,clojure]
----
(require '[tarayo.core :as tarayo])
;; => nil
----

=== Connection SMTP server

`tarayo.core/connect` is a function to connect SMTP server. +
You need to call `tarayo.core/close` function before quitting, or use https://clojuredocs.org/clojure.core/with-open[`with-open`] macro.

[source,clojure]
----
(type (tarayo/connect {:host "localhost" :port 25}))
;; => tarayo.core.SMTPConnection
----

Other examples are follows:

SSL connection::
`(tarayo/connect {:host "localhost" :port 465 :ssl.enable true})`
TLS connection::
`(tarayo/connect {:host "localhost" :port 587 :starttls.enable true})`
Connection with user authentication::
`(tarayo/connect {:host "localhost" :port 25 :user "USERNAME" :password "PASSWORD"})`

=== Sending mails

==== Text mail

[source,clojure]
----
(with-open [conn (tarayo/connect {:host "localhost" :port 25})]
(tarayo/send! conn {:from "[email protected]"
:to "[email protected]"
:subject "hello"
:body "world"}))
;; => {:result :success, :code 250, :message "250 OK\n"}
----

==== HTML mail

[source,clojure]
----
(with-open [conn (tarayo/connect {:host "localhost" :port 25})]
(tarayo/send! conn {:from "[email protected]"
:to "[email protected]"
:subject "hello"
:content-type "text/html"
:body "

world

"}))
;; => {:result :success, :code 250, :message "250 OK\n"}
----

==== Reply to

[source,clojure]
----
(with-open [conn (tarayo/connect {:host "localhost" :port 25})]
(tarayo/send! conn {:from "[email protected]"
:to "[email protected]"
:reply-to "[email protected]"
:subject "hello"
:body "world"}))
;; => {:result :success, :code 250, :message "250 OK\n"}
----

==== Attachment file

[source,clojure]
----
(require '[clojure.java.io :as io])
;; => nil

(with-open [conn (tarayo/connect {:host "localhost" :port 25})]
(tarayo/send! conn {:from "[email protected]"
:to "[email protected]"
:subject "hello"
;; Default multipart type is "mixed"
:body [;; string content will be handled as "text message" while others are handled as "attachment file"
{:content "world"}
;; If you don't specify `:content-type`, tarayo will detect it using Apache Tika automatically.
{:content (io/file "test/resources/file")}
;; Of cource, you can specify `:content-type` manually.
{:content (io/file "test/resources/image.png") :content-type "image/png"}
;; You could also use byte array for `:content`.
{:content (java.nio.file.Files/readAllBytes (.toPath (io/file "test/resources/image.png")))
;; In this case, `:content-type` and `:filename` must be specified.
:content-type "image/png" :filename "new.png"}]}))
;; => {:result :success, :code 250, :message "250 OK\n"}
----

==== Multipart/alternative

[source,clojure]
----
(with-open [conn (tarayo/connect {:host "localhost" :port 25})]
(tarayo/send! conn {:from "[email protected]"
:to "[email protected]"
:subject "hello"
:multipart "alternative"
:body [{:content-type "text/plain" :content "world"}
{:content-type "text/html" :content "

wold

"}]}))
;; => {:result :success, :code 250, :message "250 OK\n"}
----

==== Inline image (Multipart/related)

[source,clojure]
----
(require '[clojure.java.io :as io]
'[tarayo.mail.mime.id :as mime-id])
;; => nil

(with-open [conn (tarayo/connect {:host "localhost" :port 25})]
(let [content-id (mime-id/get-random)]
(tarayo/send! conn {:from "[email protected]"
:to "[email protected]"
:subject "hello"
:multipart "related"
:body [{:content (str " world") :content-type "text/html"}
;; containing id will be handled as "inline attachment file"
{:content (io/file "test/resources/image.png") :id content-id}]})))
;; => {:result :success, :code 250, :message "250 OK\n"}
----

=== Use for Gmail API

Like above, tarayo only supports SMTP, but you can also use for generating parameter to call Gmail API.

https://developers.google.com/gmail/api/v1/reference/users/messages/send

> The entire email message in an RFC 2822 formatted and base64url encoded string. Returned in messages.get and drafts.get responses when the format=RAW parameter is supplied.

To generate this parameter, you can use `tarayo.mail.mime`.

[source,clojure]
----
(require '[tarayo.mail.mime :as mime]
'[tarayo.mail.session :as session])
;; => nil

(defn- mime-message->raw-string [^jakarta.mail.internet.MimeMessage mime-msg]
(let [buf (java.io.ByteArrayOutputStream.)]
(.writeTo mime-msg buf)
(org.apache.commons.codec.binary.Base64/encodeBase64URLSafeString (.toByteArray buf))))
;; => any?

(let [msg {:from "[email protected]"
:to "[email protected]"
:subject "hello"
:body "world"}
mime-msg (mime/make-message (session/make-session) msg)]
(mime-message->raw-string mime-msg))
;; => string?
----

== Stubbing

Example using https://github.com/bguthrie/shrubbery[shrubbery].

[source,clojure]
----
(require '[shrubbery.core :as shrubbery])
;; => nil

(let [conn (shrubbery/stub
tarayo/ISMTPConnection
{:send! "ok"
:connected? true
:close true})]
(tarayo/send! conn "foo"))
;; => "ok"
----

== License

Copyright 2020-2023 Toyokumo,Inc.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.