<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ilhan Ates</title>
    <description>The latest articles on DEV Community by Ilhan Ates (@ilhanates).</description>
    <link>https://dev.to/ilhanates</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F446688%2Fe00f9cd5-67fe-4cda-98bc-68d068d8782a.jpeg</url>
      <title>DEV Community: Ilhan Ates</title>
      <link>https://dev.to/ilhanates</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ilhanates"/>
    <language>en</language>
    <item>
      <title>Move an already running process to screen</title>
      <dc:creator>Ilhan Ates</dc:creator>
      <pubDate>Mon, 02 Oct 2023 21:01:00 +0000</pubDate>
      <link>https://dev.to/ilhanates/move-an-already-running-process-to-screen-l7</link>
      <guid>https://dev.to/ilhanates/move-an-already-running-process-to-screen-l7</guid>
      <description>&lt;p&gt;You've realized some command you ran on your remote server is taking long, and want to move it to a Screen session. Tough situation, easy solution!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use top or htop to grab the PID of the process.&lt;/li&gt;
&lt;li&gt;Open screen in another ssh session / terminal tab.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;&lt;a href="https://github.com/nelhage/reptyr" rel="noopener noreferrer"&gt;reptyr&lt;/a&gt;&lt;/strong&gt; (&lt;code&gt;reptyr PID&lt;/code&gt;) to attach it back!&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>linux</category>
      <category>tutorial</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Building Multi-Arch Docker Images on Github Actions</title>
      <dc:creator>Ilhan Ates</dc:creator>
      <pubDate>Mon, 02 Oct 2023 17:13:22 +0000</pubDate>
      <link>https://dev.to/ilhanates/building-multi-arch-docker-images-on-github-actions-1ekc</link>
      <guid>https://dev.to/ilhanates/building-multi-arch-docker-images-on-github-actions-1ekc</guid>
      <description>&lt;p&gt;I recently needed to create multi-arch images so that I could spin up containers on my arm-based laptop. Github Actions only runs on x64-86 VMs, which can make building images for other architectures tricky.&lt;/p&gt;

&lt;h3&gt;
  
  
  Regular old Docker Build
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Docker&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;main'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;docker&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repository&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Login to Docker Hub&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/login-action@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DOCKERHUB_USERNAME }}&lt;/span&gt;
          &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.DOCKERHUB_TOKEN }}&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and push&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/build-push-action@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user/app:latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the above Github Actions file, we could build and push to Docker Hub easily. Now let's check out how we can use &lt;code&gt;buildx&lt;/code&gt; to build for multiple architectures.&lt;/p&gt;

&lt;h3&gt;
  
  
  QEMU and Buildx
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;QEMU is a generic and open source machine emulator and virtualizer. When used as a machine emulator, QEMU can run OSes and programs made for one machine (e.g. an ARM board) on a different machine (e.g. your own PC). By using dynamic translation, it achieves very good performance.&lt;/p&gt;

&lt;p&gt;Docker buildx is a Docker plugin that extends the building ability of images by using the BuildKit builder. It allows us to build images for different platforms and architectures.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With a combination of &lt;strong&gt;QEMU&lt;/strong&gt; and &lt;strong&gt;buildx&lt;/strong&gt;,  which are conveniently also available as Github Actions, we can easily get our images built on emulated OSes and push onto the docker registry with multi-platform support!&lt;/p&gt;

&lt;p&gt;Add the following after the registry checkout on our Github Actions workflow file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up QEMU&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/setup-qemu-action@v2&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;platforms&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;arm64,arm'&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Docker buildx&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/setup-buildx-action@v2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: The QEMU setup step has to be put &lt;em&gt;before&lt;/em&gt; the buildx step!&lt;/p&gt;

&lt;p&gt;By default, &lt;code&gt;setup-qemu-action&lt;/code&gt; will create many VMs, most of which you might not care about. Make sure to put in the platforms you actually want to build for in the &lt;code&gt;platforms:&lt;/code&gt; field to limit this to only ones you actually need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Arch-specific Dockerfile instructions
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;docker-build-push-action&lt;/code&gt; will provide the &lt;code&gt;--platform&lt;/code&gt; flag to &lt;code&gt;docker buildx&lt;/code&gt;. This will set the following &lt;a href="https://docs.docker.com/build/guide/build-args/" rel="noopener noreferrer"&gt;build ARGs&lt;/a&gt; automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;TARGETPLATFORM&lt;/code&gt; - platform of the build result. Eg &lt;code&gt;linux/amd64&lt;/code&gt;, &lt;code&gt;linux/arm/v7&lt;/code&gt;, &lt;code&gt;windows/amd64&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TARGETOS&lt;/code&gt; - OS component of &lt;code&gt;TARGETPLATFORM&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TARGETARCH&lt;/code&gt; - architecture component of &lt;code&gt;TARGETPLATFORM&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;TARGETVARIANT&lt;/code&gt; - variant component of &lt;code&gt;TARGETPLATFORM&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BUILDPLATFORM&lt;/code&gt; - platform of the node performing the build.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BUILDOS&lt;/code&gt; - OS component of &lt;code&gt;BUILDPLATFORM&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BUILDARCH&lt;/code&gt; - architecture component of &lt;code&gt;BUILDPLATFORM&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;BUILDVARIANT&lt;/code&gt; - variant component of &lt;code&gt;BUILDPLATFORM&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To use these ARGs in your Dockerfiles, you need to add them like the following example grabbed from Docker docs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; alpine&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; TARGETPLATFORM&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"I'm building for &lt;/span&gt;&lt;span class="nv"&gt;$TARGETPLATFORM&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  End result
&lt;/h3&gt;

&lt;p&gt;As a result, we can build and push multi-arch images by emulating other architectures on Github's x86_64 VMs using &lt;code&gt;QEMU&lt;/code&gt; and building with &lt;code&gt;docker buildx&lt;/code&gt;. We can even do arch-specific actions by using the ARGs automatically set by &lt;code&gt;buildx&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Closing notes
&lt;/h3&gt;

&lt;p&gt;Although this is convenient, no land without stones, or meat without bones.&lt;/p&gt;

&lt;p&gt;There is one big and one relatively small problem this might cause for you.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Super long build times
&lt;/h4&gt;

&lt;p&gt;Your builds might be taking very long after enabling multi-arch builds. This seems to be a known problem with emulating, but you could use some tricks to make less emulated code run while building.&lt;/p&gt;

&lt;p&gt;In my case, I was building a Go application inside a build image, then copying that onto a target image in a two-step Dockerfile like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.20-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;go &lt;span class="nb"&gt;env&lt;/span&gt; &lt;span class="nt"&gt;-w&lt;/span&gt; &lt;span class="nv"&gt;GOPRIVATE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;github.com/myorganization

&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; GITHUB_TOKEN&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"machine github.com login github password &lt;/span&gt;&lt;span class="nv"&gt;$GITHUB_TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /root/.netrc

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go build &lt;span class="s2"&gt;"-ldflags=-s -w"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /my-application cmd/main.go


&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; alpine:3.8&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /my-application /app/my-app&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; /app/my-app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of running the &lt;code&gt;go build&lt;/code&gt; inside the Dockerfile, I switched to building directly inside the Github Actions using &lt;code&gt;GOOS&lt;/code&gt; and &lt;code&gt;GOARCH&lt;/code&gt; variables to specify building for a specific arch:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Go &lt;/span&gt;&lt;span class="m"&gt;1.20&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-go@v1&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;go-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.20&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup netrc&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;echo "machine github.com login github password ${{ secrets.ACCESS_TOKEN }}" &amp;gt; ~/.netrc&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build application&lt;/span&gt;
  &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
    &lt;span class="s"&gt;go env -w GOPRIVATE=github.com/myorganization&lt;/span&gt;
    &lt;span class="s"&gt;GOOS=linux GOARCH=amd64 go build "-ldflags=-s -w" -o build/my-app-amd64 cmd/main.go&lt;/span&gt;
    &lt;span class="s"&gt;GOOS=linux GOARCH=arm64 go build "-ldflags=-s -w" -o build/my-app-arm64 cmd/main.go&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then copying those builds into the container using the buildx ARGs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; alpine:3.8&lt;/span&gt;

&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; TARGETARCH&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; build/my-app-${TARGETARCH} /app/my-app&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; /app/my-app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the end, this lowered the whole execution time from ~6m to ~1,5m. I've heard people lower theirs down from ~1h to ~15m as well.&lt;/p&gt;

&lt;h4&gt;
  
  
  Pushing to AWS ECR creates multiple images
&lt;/h4&gt;

&lt;p&gt;If you're pushing to &lt;a href="https://aws.amazon.com/ecr/" rel="noopener noreferrer"&gt;AWS ECR&lt;/a&gt;, you might realize one push is creating many untagged images of type &lt;code&gt;Image&lt;/code&gt; and one image of type &lt;code&gt;Image Index&lt;/code&gt; containing all the tags, which looks like this: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2iqouxkpn3qvvb64o8jk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2iqouxkpn3qvvb64o8jk.png" alt="image" width="450" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is actually normal, since pushing a multi-arch image really is just pushing untagged images for each arch and using an Image Index to redirect the user to the correct architecture image when pulling. The arch-specific images are untagged so that they cannot be easily discovered and pulled, and instead the Image Index that handles this is reached.&lt;/p&gt;

&lt;p&gt;It looks like AWS might &lt;a href="https://github.com/aws/containers-roadmap/issues/1596" rel="noopener noreferrer"&gt;update the UI&lt;/a&gt; to make this look less cluttered in the future.&lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/build/building/multi-platform/" rel="noopener noreferrer"&gt;https://docs.docker.com/build/building/multi-platform/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.thesparktree.com/docker-multi-arch-github-actions" rel="noopener noreferrer"&gt;https://blog.thesparktree.com/docker-multi-arch-github-actions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/aws/containers-roadmap/issues/1596" rel="noopener noreferrer"&gt;https://github.com/aws/containers-roadmap/issues/1596&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tutorial</category>
      <category>docker</category>
      <category>githubactions</category>
      <category>devops</category>
    </item>
    <item>
      <title>Send emails using utopia-php/messaging and MailSlurp</title>
      <dc:creator>Ilhan Ates</dc:creator>
      <pubDate>Mon, 02 Oct 2023 17:11:33 +0000</pubDate>
      <link>https://dev.to/ilhanates/send-emails-using-utopia-phpmessaging-and-mailslurp-3dpk</link>
      <guid>https://dev.to/ilhanates/send-emails-using-utopia-phpmessaging-and-mailslurp-3dpk</guid>
      <description>&lt;p&gt;If you've ever used a web application, chances are quite high that you've received an email from it.&lt;/p&gt;

&lt;p&gt;If you're building a web application, chances are you might also want to &lt;em&gt;send&lt;/em&gt; an email from it.&lt;/p&gt;

&lt;p&gt;Well, using &lt;a href="https://mailslurp.com" rel="noopener noreferrer"&gt;MailSlurp&lt;/a&gt; and &lt;a href="https://github.com/utopia-php/messaging" rel="noopener noreferrer"&gt;utopia-php/messaging&lt;/a&gt;, you can do that with just a couple lines!&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting Started
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1. Getting the MailSlurp API key
&lt;/h4&gt;

&lt;p&gt;First we will go ahead and sign up for a free personal MailSlurp account.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Go to mailslurp.com and click on Sign Up.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sign up using your email or one of the OAuth providers.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltn2rjzt2syyk6gg0yp8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltn2rjzt2syyk6gg0yp8.png" alt="image" width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go to settings and copy your API key.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltd5ujo7jx6ldcmrq9gt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltd5ujo7jx6ldcmrq9gt.png" alt="image" width="800" height="346"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Optionally setup a domain under &lt;code&gt;Inboxes &amp;gt; Domains&lt;/code&gt; and create an inbox under the &lt;code&gt;Inbox&lt;/code&gt; tab. We will skip for the simplicity of this tutorial. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that unfortunately with a free plan, you can't send emails to big providers as stated &lt;a href="https://www.mailslurp.com/support/free-plan-limitations/" rel="noopener noreferrer"&gt;here&lt;/a&gt;, so you might also want to upgrade your account.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Using utopia-php/messaging
&lt;/h4&gt;

&lt;p&gt;Now that we got the API key, you will need to install utopia-php/messaging in your PHP project, following their &lt;a href="https://github.com/utopia-php/messaging#email" rel="noopener noreferrer"&gt;README&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;composer require utopia-php/messaging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;\Utopia\Messaging\Messages\Email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;\Utopia\Messaging\Adapters\Email\MailSlurp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'you@email.com'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'Hello World'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&amp;lt;h1&amp;gt;Hello World&amp;lt;/h1&amp;gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'your-inbox-identifier@mailslurp.com'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$messaging&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;MailSlurp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'YOUR_API_KEY'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$messaging&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And simple as that, the email should be sent!&lt;/p&gt;

</description>
      <category>php</category>
      <category>tutorial</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
