{"id":25323795,"url":"https://github.com/spinoco/fs2-mail","last_synced_at":"2025-07-30T04:08:44.700Z","repository":{"id":46141939,"uuid":"113033813","full_name":"Spinoco/fs2-mail","owner":"Spinoco","description":"asynchronous library for sending and receiving mail via fs2._ ","archived":false,"fork":false,"pushed_at":"2022-10-24T17:20:39.000Z","size":225,"stargazers_count":44,"open_issues_count":5,"forks_count":9,"subscribers_count":7,"default_branch":"series/0.4","last_synced_at":"2025-04-04T17:47:23.339Z","etag":null,"topics":["asynchronous","decoding","fs2","imap","javamail","mail","mime","receive-emails","scala","smtp","streaming"],"latest_commit_sha":null,"homepage":null,"language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Spinoco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-12-04T11:23:40.000Z","updated_at":"2023-06-23T02:09:19.000Z","dependencies_parsed_at":"2022-09-09T09:30:56.560Z","dependency_job_id":null,"html_url":"https://github.com/Spinoco/fs2-mail","commit_stats":null,"previous_names":[],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/Spinoco/fs2-mail","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Spinoco%2Ffs2-mail","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Spinoco%2Ffs2-mail/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Spinoco%2Ffs2-mail/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Spinoco%2Ffs2-mail/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Spinoco","download_url":"https://codeload.github.com/Spinoco/fs2-mail/tar.gz/refs/heads/series/0.4","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Spinoco%2Ffs2-mail/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267808142,"owners_count":24147366,"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","status":"online","status_checked_at":"2025-07-30T02:00:09.044Z","response_time":70,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["asynchronous","decoding","fs2","imap","javamail","mail","mime","receive-emails","scala","smtp","streaming"],"created_at":"2025-02-14T00:44:33.053Z","updated_at":"2025-07-30T04:08:44.622Z","avatar_url":"https://github.com/Spinoco.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fs2-mail\n\nAsynchronous, non-blocking IMAP/SMTP client for receiving and sending e-mails for scala.\n\n[![Build Status](https://travis-ci.org/Spinoco/fs2-mail.svg?branch=series/0.2)](https://travis-ci.org/Spinoco/fs2-mail)\n[![Gitter Chat](https://badges.gitter.im/functional-streams-for-scala/fs2.svg)](https://gitter.im/fs2-mail/Lobby)\n\n## Overview\n\nfs2-mail is simple, minimalistic, streaming, asynchronous and non-blocking client for receiving and sending emails \nfor scala implemented in fs2 library. Traditionally sending and receiving emails in JVM world is done with \nJava's JavaMail API, that allows rich set of functionality. Albeit rich and powerful, JavaMail \nis build on top of fully blocking API. That may present limitations when working with asynchronous and \nstreaming libraries, and that is exactly where fs2-mail fits in.  \n\nUnlike JavaMail, fs2-mail is fully non-blocking, streaming allowing to process emails with minimal memory constrains \nwith full utilization of modern multi-core CPUs. All processing (encoding, decoding) of emails \nis fully asynchronous and non-blocking. So for example receiving or sending emails over slower network \nconnections will work perfectly fine and will automatically adjust to speed of the target/source server. That way, \nyou can write clients that may send and receive hundreds or thousands emails concurrently fully saturating \nserver and internet connection capacity. \n\n \n## Features\n\nfs-mail currently implements: \n\n- IMAP to receive emails\n- SMTP to send emails\n\nBoth variants may use SSL depending whether clients are created with plaintext or SSL socket. \n\n\n## SBT\n\nAdd this to your sbt build file :\n\nfor fs2 0.10.x series:\n\n```\nlibraryDependencies += \"com.spinoco\" %% \"fs2-mail\" % \"0.2.0\"\n```\n\nfor fs2 0.9.x series:\n\n```\nlibraryDependencies += \"com.spinoco\" %% \"fs2-mail\" % \"0.1.1\"\n```\n\n\n### Dependencies\n\nversion  |    scala  |   fs2  |  scodec | shapeless      \n---------|-----------|--------|---------|----------- \n0.4.0-M2    | 2.11, 2.12| 1.0.0-M2 | 1.10.3  | 2.3.2\n0.2.0    | 2.11, 2.12| 0.10.5 | 1.10.3  | 2.3.2\n0.1.1    | 2.11, 2.12| 0.9.7  | 1.10.3  | 2.3.2\n\n\n## Usage\n\nfs2-mail has simple, minimalistic API, that allows straightforward usage. \n\n### Sending emails\n\nTo send emails, fs2-mail uses SMTP protocol. Following is the simple example of minimalistic client that \nuses single SMTP connection to send single message: \n\n```scala\nimport java.net.InetSocketAddress\nimport java.time.ZonedDateTime\n\nimport cats.effect.IO\nimport fs2._ \nimport fs2.crypto.TLSEngine\nimport fs2.crypto.io.tcp.TLSSocket\n\nimport shapeless.tag\n\nimport spinoco.fs2.mail.smtp\nimport spinoco.fs2.mail.interop.StringChunk\nimport spinoco.protocol.mail.EmailAddress\nimport spinoco.protocol.mail.EMailHeader\n\n\n\n\nio.tcp.client[IO](new InetSocketAddress(\"imap.gmail.com\", 993)).flatMap { tcpSocket =\u003e\nStream.eval(TLSEngine[IO](clientTLS)).flatMap { tlsEngine =\u003e\nStream.eval(TLSSocket[IO](tcpSocket, tlsEngine)).flatMap { tlsSocket =\u003e\nsmtp.client(tlsSocket).evalMap { smtpClient =\u003e \n\n    val header: EMailHeader = EMailHeader(\n      subject = \"Hello from fs2-mail\"\n      , date = ZonedDateTime.now\n      , from = EmailAddress(\"alice\", \"mail.com\", None)\n      , to = EmailAddress(\"bob\", \"mail.com\", None)\n    )\n    val body: Stream[IO, Char] = Stream.chunk(StringChunk(\"A simple text-only email from fs2-mail.\")).covary[IO]\n\n    smtpClient.connect(\"gmail.com\") \u003e\u003e\n    smtpClient.login(\"userName\", \"password\") \u003e\u003e\n    smtpClient.sendText(tag[EmailAddress](\"alice@mail.com\"), Seq(tag[EmailAddress](\"bob@mail.com\")), header, body)\n    \n\n    \n}}}}.run.unsafeRun()\n\n```\n\nApart from sending simple emails, fs2-mail also allows to send MIME encoded (inclusive multipart) data. \nTo send such emails, that perhaps fetch their content not only from the strictly defined data but perhaps \nfrom data stored on filesystem or central data storage following construct (replacing the `smtp.sendText` in example above).\n\n```scala\n\nimport spinoco.protocol.mime._\nimport java.nio.file.Paths\n\nval fileGifSource: Stream[F, Byte] = ??? // i.e. load from the \nval body = MIMEPart.file(\"part-id\", \"file.gif\", MediaType.`image/gif`, fs2.io.file.readAll(Paths.get(\"/some/file/location/file.gif\")))  \n\nsmtpClient.send(tag[EmailAddress](\"alice@mail.com\"), Seq(tag[EmailAddress](\"bob@mail.com\")), header, body)\n\n```\n\n### Receiving emails\n\nTo receive emails, fs2 supports IMAP v 4.1 protocol. User may search emails, perform various email actions,\ndownload attachment (with automatical decoding according to their mime type). \n\nMinimalistic example of fetching ... \n\n(Note this to run requires Spinoco fs2-crypto in project dependencies)\n\n```scala\n\nimport java.net.InetSocketAddress\nimport java.time.ZonedDateTime\n\nimport fs2._\nimport fs2.util.syntax._ \nimport spinoco.fs2.crypto.io.tcp.TLSSocket\n\nimport shapeless.tag\n\nimport spinoco.fs2.mail.imap \nimport spinoco.fs2.mail.imap.MailboxName\nimport spinoco.fs2.mail.imap.IMAPSearchTerm\n\n\n io.tcp.client[IO](new InetSocketAddress(\"imap.gmail.com\", 993)).flatMap { tcpSocket =\u003e \n  Stream.eval(TLSSocket[IO](tcpSocket, clientTLS)) flatMap { tlsSocket =\u003e\n  imap.client[IO](tlsSocket) evalMap { imapClient =\u003e\n    // login with supplied credentials\n    imapClient.login(\"EMAIL\", \"PASSWORD\") \u003e\u003e\n    // check for imap server capabilities \n    imapClient.capability.flatMap { imapServerCapabilities =\u003e\n    // list mailboxes given specific criteria\n    imapClient.list(\"\", \"*\").flatMap { imapServerMailboxes =\u003e \n    // select email mailbox\n    imapClient.select(tag[MailboxName](\"INBOX\")).flatMap { inboxStatus =\u003e\n    // search mailbox for mail with specified id\n    imapClient.search(IMAPSearchTerm.Header(\"Message-ID\", \"your-message-id\")).flatMap { searchResult =\u003e   \n    // print email headers from 42000 to 4238\n    imapClient.emailHeaders(4200l to 4248l).map { hdr =\u003e println(s\"HEADER: $hdr\") }.run  \n      \n\n    }}}}\n\n  }}}\n  .run.unsafeRun\n\n```\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspinoco%2Ffs2-mail","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fspinoco%2Ffs2-mail","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fspinoco%2Ffs2-mail/lists"}