{"id":22092870,"url":"https://github.com/toyokumo/tarayo","last_synced_at":"2025-12-16T07:14:54.392Z","repository":{"id":42128145,"uuid":"175773321","full_name":"toyokumo/tarayo","owner":"toyokumo","description":":love_letter: SMTP client library for Clojure. That’s it.","archived":false,"fork":false,"pushed_at":"2024-08-07T07:36:29.000Z","size":132,"stargazers_count":65,"open_issues_count":4,"forks_count":4,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-04-28T14:21:30.472Z","etag":null,"topics":["clojure","smtp-client"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/toyokumo.png","metadata":{"files":{"readme":"README.adoc","changelog":"CHANGELOG.adoc","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-03-15T07:49:17.000Z","updated_at":"2025-04-08T20:02:01.000Z","dependencies_parsed_at":"2024-04-01T02:45:07.820Z","dependency_job_id":"3035453d-867c-4062-bd20-07f3ccce07e4","html_url":"https://github.com/toyokumo/tarayo","commit_stats":{"total_commits":132,"total_committers":2,"mean_commits":66.0,"dds":0.007575757575757569,"last_synced_commit":"3a5499a7d829dab6eb19d9deb5747f18750c9488"},"previous_names":["liquidz/tarayo"],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toyokumo%2Ftarayo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toyokumo%2Ftarayo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toyokumo%2Ftarayo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toyokumo%2Ftarayo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/toyokumo","download_url":"https://codeload.github.com/toyokumo/tarayo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251326859,"owners_count":21571637,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clojure","smtp-client"],"created_at":"2024-12-01T03:11:11.431Z","updated_at":"2025-12-16T07:14:54.378Z","avatar_url":"https://github.com/toyokumo.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"= tarayo\n:toc:\n:toc-placement: preamble\n:toclevels: 2\n\n// Need some preamble to get TOC:\n{empty}\n\nSMTP client library for Clojure. That's it.\n\n+++\n\u003cp\u003e\n  \u003ca href=\"https://github.com/toyokumo/tarayo/actions/workflows/lint-and-test.yml\"\u003e\n    \u003cimg src=\"https://github.com/toyokumo/tarayo/actions/workflows/lint-and-test.yml/badge.svg\" alt=\"Lint and Test\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://codecov.io/gh/toyokumo/tarayo\"\u003e\n    \u003cimg src=\"https://codecov.io/gh/toyokumo/tarayo/branch/master/graph/badge.svg\" alt=\"Codecov\" /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://cljdoc.org/d/toyokumo/tarayo/CURRENT\"\u003e\n    \u003cimg src=\"https://cljdoc.org/badge/toyokumo/tarayo\" /\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n+++\n\n== Why tarayo?\n\nTarayo is heavily inspired by https://github.com/drewr/postal[drewr/postal].\n\n* Only targets SMTP\n** Provide only one feature.\n** Use https://github.com/drewr/postal[drewr/postal] for `sendmail`.\n* Explicit connection\n** Handle the connection manually.\n* Well tested\n\n\"Tarayo\" is a tree name called \"Tree of post office\" in Japan.\n\n== Usage\n\n\nlink:https://clojars.org/toyokumo/tarayo[image:https://img.shields.io/clojars/v/toyokumo/tarayo.svg[]]\n\n[source,clojure]\n----\n(require '[tarayo.core :as tarayo])\n;; =\u003e nil\n----\n\n=== Connection SMTP server\n\n`tarayo.core/connect` is a function to connect SMTP server. +\nYou need to call `tarayo.core/close` function before quitting, or use https://clojuredocs.org/clojure.core/with-open[`with-open`] macro.\n\n[source,clojure]\n----\n(type (tarayo/connect {:host \"localhost\" :port 25}))\n;; =\u003e tarayo.core.SMTPConnection\n----\n\nOther examples are follows:\n\nSSL connection::\n`(tarayo/connect {:host \"localhost\" :port 465 :ssl.enable true})`\nTLS connection::\n`(tarayo/connect {:host \"localhost\" :port 587 :starttls.enable true})`\nConnection with user authentication::\n`(tarayo/connect {:host \"localhost\" :port 25 :user \"USERNAME\" :password \"PASSWORD\"})`\n\n=== Sending mails\n\n==== Text mail\n\n[source,clojure]\n----\n(with-open [conn (tarayo/connect {:host \"localhost\" :port 25})]\n  (tarayo/send! conn {:from \"alice@example.com\"\n                      :to \"bob@example.com\"\n                      :subject \"hello\"\n                      :body \"world\"}))\n;; =\u003e {:result :success, :code 250, :message \"250 OK\\n\"}\n----\n\n==== HTML mail\n\n[source,clojure]\n----\n(with-open [conn (tarayo/connect {:host \"localhost\" :port 25})]\n  (tarayo/send! conn {:from \"alice@example.com\"\n                      :to \"bob@example.com\"\n                      :subject \"hello\"\n                      :content-type \"text/html\"\n                      :body \"\u003ch1\u003eworld\u003c/h1\u003e\"}))\n;; =\u003e {:result :success, :code 250, :message \"250 OK\\n\"}\n----\n\n==== Reply to\n\n[source,clojure]\n----\n(with-open [conn (tarayo/connect {:host \"localhost\" :port 25})]\n  (tarayo/send! conn {:from \"alice@example.com\"\n                      :to \"bob@example.com\"\n                      :reply-to \"charlie@example.com\"\n                      :subject \"hello\"\n                      :body \"world\"}))\n;; =\u003e {:result :success, :code 250, :message \"250 OK\\n\"}\n----\n\n==== Attachment file\n\n[source,clojure]\n----\n(require '[clojure.java.io :as io])\n;; =\u003e nil\n\n(with-open [conn (tarayo/connect {:host \"localhost\" :port 25})]\n  (tarayo/send! conn {:from \"alice@example.com\"\n                      :to \"bob@example.com\"\n                      :subject \"hello\"\n                      ;; Default multipart type is \"mixed\"\n                      :body [;; string content will be handled as \"text message\" while others are handled as \"attachment file\"\n                             {:content \"world\"}\n                             ;; If you don't specify `:content-type`, tarayo will detect it using Apache Tika automatically.\n                             {:content (io/file \"test/resources/file\")}\n                             ;; Of cource, you can specify `:content-type` manually.\n                             {:content (io/file \"test/resources/image.png\") :content-type \"image/png\"}\n                             ;; You could also use byte array for `:content`.\n                             {:content (java.nio.file.Files/readAllBytes (.toPath (io/file \"test/resources/image.png\")))\n                              ;; In this case, `:content-type` and `:filename` must be specified.\n                              :content-type \"image/png\" :filename \"new.png\"}]}))\n;; =\u003e {:result :success, :code 250, :message \"250 OK\\n\"}\n----\n\n==== Multipart/alternative\n\n[source,clojure]\n----\n(with-open [conn (tarayo/connect {:host \"localhost\" :port 25})]\n  (tarayo/send! conn {:from \"alice@example.com\"\n                      :to \"bob@example.com\"\n                      :subject \"hello\"\n                      :multipart \"alternative\"\n                      :body [{:content-type \"text/plain\" :content \"world\"}\n                             {:content-type \"text/html\" :content \"\u003ch1\u003ewold\u003c/h1\u003e\"}]}))\n;; =\u003e {:result :success, :code 250, :message \"250 OK\\n\"}\n----\n\n==== Inline image (Multipart/related)\n\n[source,clojure]\n----\n(require '[clojure.java.io :as io]\n         '[tarayo.mail.mime.id :as mime-id])\n;; =\u003e nil\n\n(with-open [conn (tarayo/connect {:host \"localhost\" :port 25})]\n  (let [content-id (mime-id/get-random)]\n    (tarayo/send! conn {:from \"alice@example.com\"\n                        :to \"bob@example.com\"\n                        :subject \"hello\"\n                        :multipart \"related\"\n                        :body [{:content (str \"\u003cimg src=\\\"cid:\" content-id \"\\\" /\u003e world\") :content-type \"text/html\"}\n                               ;; containing id will be handled as \"inline attachment file\"\n                               {:content (io/file \"test/resources/image.png\") :id content-id}]})))\n;; =\u003e {:result :success, :code 250, :message \"250 OK\\n\"}\n----\n\n=== Use for Gmail API\n\nLike above, tarayo only supports SMTP, but you can also use for generating parameter to call Gmail API.\n\nhttps://developers.google.com/gmail/api/v1/reference/users/messages/send\n\n\u003e 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.\n\nTo generate this parameter, you can use `tarayo.mail.mime`.\n\n[source,clojure]\n----\n(require '[tarayo.mail.mime :as mime]\n         '[tarayo.mail.session :as session])\n;; =\u003e nil\n\n(defn- mime-message-\u003eraw-string [^jakarta.mail.internet.MimeMessage mime-msg]\n  (let [buf (java.io.ByteArrayOutputStream.)]\n    (.writeTo mime-msg buf)\n    (org.apache.commons.codec.binary.Base64/encodeBase64URLSafeString (.toByteArray buf))))\n;; =\u003e any?\n\n(let [msg {:from \"alice@example.com\"\n           :to \"bob@example.com\"\n           :subject \"hello\"\n           :body \"world\"}\n      mime-msg (mime/make-message (session/make-session) msg)]\n  (mime-message-\u003eraw-string mime-msg))\n;; =\u003e string?\n----\n\n==  Stubbing\n\nExample using https://github.com/bguthrie/shrubbery[shrubbery].\n\n[source,clojure]\n----\n(require '[shrubbery.core :as shrubbery])\n;; =\u003e nil\n\n(let [conn (shrubbery/stub\n            tarayo/ISMTPConnection\n            {:send! \"ok\"\n             :connected? true\n             :close true})]\n  (tarayo/send! conn \"foo\"))\n;; =\u003e \"ok\"\n----\n\n== License\n\nCopyright 2020-2025 Toyokumo,Inc.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftoyokumo%2Ftarayo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftoyokumo%2Ftarayo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftoyokumo%2Ftarayo/lists"}