aster.cloud aster.cloud
  • /
  • Platforms
    • Public Cloud
    • On-Premise
    • Hybrid Cloud
    • Data
  • Architecture
    • Design
    • Solutions
    • Enterprise
  • Engineering
    • Automation
    • Software Engineering
    • Project Management
    • DevOps
  • Programming
    • Learning
  • Tools
  • About
  • /
  • Platforms
    • Public Cloud
    • On-Premise
    • Hybrid Cloud
    • Data
  • Architecture
    • Design
    • Solutions
    • Enterprise
  • Engineering
    • Automation
    • Software Engineering
    • Project Management
    • DevOps
  • Programming
    • Learning
  • Tools
  • About
aster.cloud aster.cloud
  • /
  • Platforms
    • Public Cloud
    • On-Premise
    • Hybrid Cloud
    • Data
  • Architecture
    • Design
    • Solutions
    • Enterprise
  • Engineering
    • Automation
    • Software Engineering
    • Project Management
    • DevOps
  • Programming
    • Learning
  • Tools
  • About
  • Programming

Announcing SwiftNIO IMAP

  • aster.cloud
  • September 6, 2022
  • 4 minute read

As part of expanding the Swift on Server ecosystem, we’re thrilled to announce the release of a new IMAPv4 parser and encoder, SwiftNIO IMAP.

This package implements:


Partner with aster.cloud
for your next big idea.
Let us know here.



From our partners:

CITI.IO :: Business. Institutions. Society. Global Political Economy.
CYBERPOGO.COM :: For the Arts, Sciences, and Technology.
DADAHACKS.COM :: Parenting For The Rest Of Us.
ZEDISTA.COM :: Entertainment. Sports. Culture. Escape.
TAKUMAKU.COM :: For The Hearth And Home.
ASTER.CLOUD :: From The Cloud And Beyond.
LIWAIWAI.COM :: Intelligence, Inside and Outside.
GLOBALCLOUDPLATFORMS.COM :: For The World's Computing Needs.
FIREGULAMAN.COM :: For The Fire In The Belly Of The Coder.
ASTERCASTER.COM :: Supra Astra. Beyond The Stars.
BARTDAY.COM :: Prosperity For Everyone.

  • Parsing IMAPv4 wire-format to type-safe Swift data structures
  • Encoding these Swift data structures to the IMAPv4 wire format
  • Extensive support for common IMAP extensions
  • High performance
  • Integration with SwiftNIO

Motivation

Email has been a indispensable part of the internet for over 40 years and is a ubiquitous part of many products and services today.

Internet Message Access Protocol (IMAP) is the most widely used open standard to retrieve email messages. It has been around for multiple decades and has evolved substantially over the years through various RFCs.

Correctly parsing and encoding IMAP is notoriously difficult. SwiftNIO IMAP reduces this difficulty by handling many subtle details of encoding and parsing IMAP, making it easier than ever to write rich and powerful email integrations with Swift on server.

This package is focused on parsing and encoding IMAP while also providing some common convenience methods related to core IMAP types. It does not implement any of busines logic related to IMAP.

A Brief Tour

The SwiftNIO IMAP targets RFC 3501, IMAP version 4rev1, and additionally supports extensions from more than 20 RFCs: RFC 2087, 2177, 2221, 2342, 2971, 3348, 3501, 3502, 3516, 3691, 4315, 4467, 4469, 4731, 4959, 5032, 5161, 5182, 5258, 5464, 5819, 6154, 6851, 7162, 7377, 7888, and 8438.

IMAP uses a text-based “human readable” wire format, and SwiftNIO IMAP bridges this to a type-safe world using modern Swift data structures. The protocol is “asymetric”: messages sent from the server follow different patterns that messages sent by the client.

Example Exchange

As a quick example, here’s part of the the exchange listed in RFC 3501 section 8, where lines starting with S: and C: are from the server and client respectively:

S:   * OK IMAP4rev1 Service Ready
C:   a001 login mrc secret
S:   a001 OK LOGIN completed
C:   a002 select inbox
S:   * 18 EXISTS
S:   * FLAGS (\Answered \Flagged \Deleted \Seen \Draft)
S:   * 2 RECENT
S:   * OK [UNSEEN 17] Message 17 is the first unseen message
S:   * OK [UIDVALIDITY 3857529045] UIDs valid
S:   a002 OK [READ-WRITE] SELECT completed

The first 3 lines would correspond to the following in SwiftNIO IMAP:

<span class="kt">Response</span><span class="o">.</span><span class="nf">untagged</span><span class="p">(</span><span class="o">.</span><span class="nf">conditionalState</span><span class="p">(</span><span class="o">.</span><span class="nf">ok</span><span class="p">(</span><span class="kt">ResponseText</span><span class="p">(</span><span class="nv">text</span><span class="p">:</span> <span class="s">"IMAP4rev1 Service Ready"</span><span class="p">))))</span>
<span class="kt">CommandStreamPart</span><span class="o">.</span><span class="nf">tagged</span><span class="p">(</span><span class="kt">TaggedCommand</span><span class="p">(</span><span class="nv">tag</span><span class="p">:</span> <span class="s">"a001"</span><span class="p">,</span> <span class="nv">command</span><span class="p">:</span> <span class="o">.</span><span class="nf">login</span><span class="p">(</span><span class="nv">username</span><span class="p">:</span> <span class="s">"mrc"</span><span class="p">,</span> <span class="nv">password</span><span class="p">:</span> <span class="s">"secret"</span><span class="p">)))</span>
<span class="kt">Response</span><span class="o">.</span><span class="nf">tagged</span><span class="p">(</span><span class="o">.</span><span class="nf">init</span><span class="p">(</span><span class="nv">tag</span><span class="p">:</span> <span class="s">"a001"</span><span class="p">,</span> <span class="nv">state</span><span class="p">:</span> <span class="o">.</span><span class="nf">ok</span><span class="p">(</span><span class="kt">ResponseText</span><span class="p">(</span><span class="nv">text</span><span class="p">:</span> <span class="s">"LOGIN completed"</span><span class="p">))))</span>

Next, up is the SELECT command and its responses, which are more interesting:

<span class="kt">CommandStreamPart</span><span class="o">.</span><span class="nf">tagged</span><span class="p">(</span><span class="kt">TaggedCommand</span><span class="p">(</span><span class="nv">tag</span><span class="p">:</span> <span class="s">"a002"</span><span class="p">,</span> <span class="nv">command</span><span class="p">:</span> <span class="o">.</span><span class="nf">select</span><span class="p">(</span><span class="kt">MailboxName</span><span class="p">(</span><span class="s">"box1"</span><span class="p">),</span> <span class="p">[])))</span>
<span class="kt">Response</span><span class="o">.</span><span class="nf">untagged</span><span class="p">(</span><span class="o">.</span><span class="nf">mailboxData</span><span class="p">(</span><span class="o">.</span><span class="nf">exists</span><span class="p">(</span><span class="mi">18</span><span class="p">)))</span>
<span class="kt">Response</span><span class="o">.</span><span class="nf">untagged</span><span class="p">(</span><span class="o">.</span><span class="nf">mailboxData</span><span class="p">(</span><span class="o">.</span><span class="nf">flags</span><span class="p">([</span><span class="o">.</span><span class="n">answered</span><span class="p">,</span> <span class="o">.</span><span class="n">flagged</span><span class="p">,</span> <span class="o">.</span><span class="n">deleted</span><span class="p">,</span> <span class="o">.</span><span class="n">seen</span><span class="p">,</span> <span class="o">.</span><span class="n">draft</span><span class="p">])))</span>
<span class="kt">Response</span><span class="o">.</span><span class="nf">untagged</span><span class="p">(</span><span class="o">.</span><span class="nf">mailboxData</span><span class="p">(</span><span class="o">.</span><span class="nf">recent</span><span class="p">(</span><span class="mi">2</span><span class="p">)))</span>
<span class="kt">Response</span><span class="o">.</span><span class="nf">untagged</span><span class="p">(</span><span class="o">.</span><span class="nf">conditionalState</span><span class="p">(</span><span class="o">.</span><span class="nf">ok</span><span class="p">(</span><span class="kt">ResponseText</span><span class="p">(</span><span class="nv">code</span><span class="p">:</span> <span class="o">.</span><span class="nf">unseen</span><span class="p">(</span><span class="mi">17</span><span class="p">),</span> <span class="nv">text</span><span class="p">:</span> <span class="s">"Message 17 is the first unseen message"</span><span class="p">))))</span>
<span class="kt">Response</span><span class="o">.</span><span class="nf">untagged</span><span class="p">(</span><span class="o">.</span><span class="nf">conditionalState</span><span class="p">(</span><span class="o">.</span><span class="nf">ok</span><span class="p">(</span><span class="kt">ResponseText</span><span class="p">(</span><span class="nv">code</span><span class="p">:</span> <span class="o">.</span><span class="nf">uidValidity</span><span class="p">(</span><span class="mi">3857529045</span><span class="p">),</span> <span class="nv">text</span><span class="p">:</span> <span class="s">"UIDs valid"</span><span class="p">))))</span>
<span class="kt">Response</span><span class="o">.</span><span class="nf">tagged</span><span class="p">(</span><span class="o">.</span><span class="nf">init</span><span class="p">(</span><span class="nv">tag</span><span class="p">:</span> <span class="s">"a002"</span><span class="p">,</span> <span class="nv">state</span><span class="p">:</span> <span class="o">.</span><span class="nf">ok</span><span class="p">(</span><span class="kt">ResponseText</span><span class="p">(</span><span class="nv">code</span><span class="p">:</span> <span class="o">.</span><span class="n">readWrite</span><span class="p">,</span> <span class="nv">text</span><span class="p">:</span> <span class="s">"SELECT completed"</span><span class="p">))))</span>

There’s more going on here than this example shows. But this gives a general idea of how things look and feel.

Read More  Exploring Swift: Property Wrappers In The Wild

Common Values

Some of the very common values used in IMAP are UIDs, message sequence numbers, and mailbox names.

SwiftNIO IMAP has a UID and SequenceNumber type, and related types such as UIDRange, UIDSet, SequenceRange, and SequenceSet. The two set types conform to SetAlgebra. And all of these have convenience methods for common operations.

Mailboxes are identified by a “modified UTF-7” encoded string. The MailboxName and MailboxPath types support decoding and encoding these, while allowing to round-trip wrongly-encoded byte strings sometimes found in the wild.

Transparent Literal Support

SwiftNIO IMAP can transparently encode and decode client messages both with the synchronizing and non-synchronizing literal encodings from the base RFC 3501 and RFC 7888 extensions.

These variations are handled transparently – for both client and server:

RFC 3501 “quoted” strings:

C: A001 LOGIN "FRED FOOBAR" "fat man"
S: A001 OK LOGIN completed

RFC 3501 command continuations:

C: A001 LOGIN {11}
S: + Ready for additional command text
C: FRED FOOBAR {7}
S: + Ready for additional command text
C: fat man
S: A001 OK LOGIN completed

RFC 7888 non-synchronizing literals:

C: A001 LOGIN {11+}
C: FRED FOOBAR {7+}
C: fat man
S: A001 OK LOGIN completed

The so-called LITERAL+ / LITERAL- support can be enabled either using a CAPABILITY response from the server or alternatively by explicitly setting encoding options.

Integration with SwiftNIO

SwiftNIO IMAP provides a pair of ChannelHandler objects that can be integrated into a SwiftNIO ChannelPipeline. This allows sending IMAP commands using NIO Channels.

The two handlers SwiftNIO IMAP provides are IMAPClientHandler and IMAPServerHandler. Each of these can be inserted into the ChannelPipeline. They can then be used to encode and decode messages. For example:

<span class="k">let</span> <span class="nv">group</span> <span class="o">=</span> <span class="kt">MultiThreadedEventLoopGroup</span><span class="p">(</span><span class="nv">numberOfThreads</span><span class="p">:</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">let</span> <span class="nv">channel</span> <span class="o">=</span> <span class="k">try</span> <span class="k">await</span> <span class="kt">ClientBootstrap</span><span class="p">(</span><span class="n">group</span><span class="p">)</span><span class="o">.</span><span class="n">channelInitializer</span> <span class="p">{</span> <span class="n">channel</span> <span class="k">in</span>
    <span class="n">channel</span><span class="o">.</span><span class="n">pipeline</span><span class="o">.</span><span class="nf">addHandler</span><span class="p">(</span><span class="kt">IMAPClientHandler</span><span class="p">())</span>
<span class="p">}</span><span class="o">.</span><span class="nf">connect</span><span class="p">(</span><span class="nv">host</span><span class="p">:</span> <span class="n">example</span><span class="o">.</span><span class="n">com</span><span class="p">,</span> <span class="nv">port</span><span class="p">:</span> <span class="mi">143</span><span class="p">)</span><span class="o">.</span><span class="nf">get</span><span class="p">()</span>

<span class="k">try</span> <span class="k">await</span> <span class="n">channel</span><span class="o">.</span><span class="nf">writeAndFlush</span><span class="p">(</span><span class="kt">CommandStreamPart</span><span class="o">.</span><span class="nf">tagged</span><span class="p">(</span><span class="kt">TaggedCommand</span><span class="p">(</span><span class="nv">tag</span><span class="p">:</span> <span class="s">"a001"</span><span class="p">,</span> <span class="nv">command</span><span class="p">:</span> <span class="o">.</span><span class="nf">login</span><span class="p">(</span><span class="nv">username</span><span class="p">:</span> <span class="s">"mrc"</span><span class="p">,</span> <span class="nv">password</span><span class="p">:</span> <span class="s">"secret"</span><span class="p">))),</span> <span class="nv">promise</span><span class="p">:</span> <span class="kc">nil</span><span class="p">)</span>

The ChannelHandlers support transparent literals, IMAP capabilities, and all of the rest of the functionality of SwiftNIO IMAP. They’re powerful building blocks for IMAP applications on both the server and client.

Read More  AWS Announces AWS BugBust—The World’s First Global Competition To Find And Fix 1 Million Software Bugs

What’s Next

The version of SwiftNIO IMAP we’re releasing today is still a prototype. We want to solicit feedback from the community.

We’ve done extensive testing of the project’s code and we believe that it’s close to being “production ready”. But we would love to have design discussions on the Swift forums about what is missing, and which bits and pieces could be improved.

Get Involved

Your feedback, experience, and contributions are very welcome!

  • Get started by trying out the SwiftNIO IMAP library on GitHub.
  • Discuss the library, suggest improvements and get help in the Swift forums.
  • Open issues for problems you find.
  • Contribute pull requests to fix any issues.

 

By Daniel Eggert
Source Swift


For enquiries, product placements, sponsorships, and collaborations, connect with us at [email protected]. We'd love to hear from you!

Our humans need coffee too! Your support is highly appreciated, thank you!

aster.cloud

Related Topics
  • Swift
  • SwiftNIO
  • SwiftNIO IMAP
You May Also Like
View Post
  • Architecture
  • Data
  • Engineering
  • People
  • Programming
  • Software Engineering
  • Technology
  • Work & Jobs

Predictions: Top 25 Careers Likely In High Demand In The Future

  • June 6, 2023
View Post
  • Programming
  • Software Engineering
  • Technology

Build a Python App to Alert You When Asteroids Are Close to Earth

  • May 22, 2023
View Post
  • Programming

Illuminating Interactions: Visual State In Jetpack Compose

  • May 20, 2023
View Post
  • Computing
  • Data
  • Programming
  • Software
  • Software Engineering

The Top 10 Data Interchange Or Data Exchange Format Used Today

  • May 11, 2023
View Post
  • Architecture
  • Programming
  • Public Cloud

From Receipts To Riches: Save Money W/ Google Cloud & Supermarket Bills – Part 1

  • May 8, 2023
View Post
  • Programming
  • Public Cloud

3 New Ways To Authorize Users To Your Private Workloads On Cloud Run

  • May 4, 2023
View Post
  • Programming
  • Public Cloud

Buffer HTTP Requests With Cloud Tasks

  • May 4, 2023
View Post
  • Programming
  • Public Cloud
  • Software
  • Software Engineering

Learn About Google Cloud’s Updated Renderer For The Maps SDK For Android

  • May 4, 2023

Stay Connected!
LATEST
  • college-of-cardinals-2025 1
    The Definitive Who’s Who of the 2025 Papal Conclave
    • May 7, 2025
  • conclave-poster-black-smoke 2
    The World Is Revalidating Itself
    • May 6, 2025
  • 3
    Conclave: How A New Pope Is Chosen
    • April 25, 2025
  • Getting things done makes her feel amazing 4
    Nurturing Minds in the Digital Revolution
    • April 25, 2025
  • 5
    AI is automating our jobs – but values need to change if we are to be liberated by it
    • April 17, 2025
  • 6
    Canonical Releases Ubuntu 25.04 Plucky Puffin
    • April 17, 2025
  • 7
    United States Army Enterprise Cloud Management Agency Expands its Oracle Defense Cloud Services
    • April 15, 2025
  • 8
    Tokyo Electron and IBM Renew Collaboration for Advanced Semiconductor Technology
    • April 2, 2025
  • 9
    IBM Accelerates Momentum in the as a Service Space with Growing Portfolio of Tools Simplifying Infrastructure Management
    • March 27, 2025
  • 10
    Tariffs, Trump, and Other Things That Start With T – They’re Not The Problem, It’s How We Use Them
    • March 25, 2025
about
Hello World!

We are aster.cloud. We’re created by programmers for programmers.

Our site aims to provide guides, programming tips, reviews, and interesting materials for tech people and those who want to learn in general.

We would like to hear from you.

If you have any feedback, enquiries, or sponsorship request, kindly reach out to us at:

[email protected]
Most Popular
  • 1
    IBM contributes key open-source projects to Linux Foundation to advance AI community participation
    • March 22, 2025
  • 2
    Co-op mode: New partners driving the future of gaming with AI
    • March 22, 2025
  • 3
    Mitsubishi Motors Canada Launches AI-Powered “Intelligent Companion” to Transform the 2025 Outlander Buying Experience
    • March 10, 2025
  • PiPiPi 4
    The Unexpected Pi-Fect Deals This March 14
    • March 13, 2025
  • Nintendo Switch Deals on Amazon 5
    10 Physical Nintendo Switch Game Deals on MAR10 Day!
    • March 9, 2025
  • /
  • Technology
  • Tools
  • About
  • Contact Us

Input your search keywords and press Enter.