# Connect to Mailpit

<Badge text="⭐ Community Toolkit" variant="tip" size="large" />

<ThemeImage
  light={mailpitIcon}
  dark={mailpitLightIcon}
  alt="Mailpit logo"
  width={100}
  height={100}
  zoomable={false}
  classOverride="float-inline-left icon"
/>

This page describes how consuming apps connect to a Mailpit resource that's already modeled in your AppHost. For the AppHost API surface — adding a Mailpit resource, the SMTP endpoint, the HTTP UI endpoint, and data volumes — see [Mailpit Hosting integration](../mailpit-host/).

When you reference a Mailpit resource from your AppHost, Aspire injects an SMTP connection string and individual connection properties into the consuming app. There isn't a dedicated Aspire client package for Mailpit, so each app passes that information to a stable SMTP library directly.

## Connection properties

Aspire injects the resource connection string as `ConnectionStrings__mailpit`. It also exposes each property as an environment variable named `[RESOURCE]_[PROPERTY]`. For instance, the `Host` property of a resource called `mailpit` becomes `MAILPIT_HOST`.

The Mailpit resource exposes the following connection properties:

| Property Name | Description                                                               |
| ------------- | ------------------------------------------------------------------------- |
| `Host`        | The hostname or IP address of the Mailpit SMTP server                     |
| `Port`        | The port number the Mailpit SMTP server is listening on (default: `1025`) |
| `Uri`         | The SMTP endpoint URI, with the format `smtp://{Host}:{Port}`             |

**Example environment variable values for a resource named `mailpit`:**

```
ConnectionStrings__mailpit=Endpoint=smtp://localhost:1025
MAILPIT_HOST=localhost
MAILPIT_PORT=1025
MAILPIT_URI=smtp://localhost:1025
```

The Mailpit web UI is a separate `http` endpoint. Open it from the resource's endpoint list in the Aspire dashboard.

## Connect from your app

Pick the language your consuming app is written in. Each example assumes your AppHost adds a Mailpit resource named `mailpit` and references it from the consuming app.

The toolkit's tested C# pattern reads the Aspire connection string and passes its `Endpoint` value to `System.Net.Mail.SmtpClient`.

#### Read the SMTP connection string

```csharp title="Program.cs"
using System.Data.Common;
using System.Net.Mail;

var connectionString =
    builder.Configuration.GetConnectionString("mailpit")
    ?? throw new InvalidOperationException("Mailpit connection string is missing.");

var connectionBuilder = new DbConnectionStringBuilder
{
    ConnectionString = connectionString,
};

var smtpEndpoint = new Uri(
    (string)connectionBuilder["Endpoint"],
    UriKind.Absolute);
```

#### Send an email

```csharp title="Program.cs"
using var client = new SmtpClient(smtpEndpoint.Host, smtpEndpoint.Port);
using var message = new MailMessage(
    from: "sender@example.com",
    to: "recipient@example.com",
    subject: "Hello from Aspire",
    body: "This email was captured by Mailpit.");

await client.SendMailAsync(message);
```

#### Register as a service

Register an SMTP client factory when multiple services need to send email:

```csharp title="Program.cs"
builder.Services.AddTransient(_ =>
    new SmtpClient(smtpEndpoint.Host, smtpEndpoint.Port));
```

:::note
Microsoft doesn't recommend `SmtpClient` for new development. You can pass the same endpoint to another SMTP library, such as [MailKit](https://github.com/jstedfast/MailKit).
:::

The following example uses the Go standard library's `net/smtp` package:

```go title="main.go"
package main

import (
    "fmt"
    "net/smtp"
    "os"
)

func main() {
    // Read Aspire-injected SMTP connection properties
    smtpHost := os.Getenv("MAILPIT_HOST")
    smtpPort := os.Getenv("MAILPIT_PORT")
    addr := fmt.Sprintf("%s:%s", smtpHost, smtpPort)

    from := "sender@example.com"
    to := []string{"recipient@example.com"}
    msg := []byte(
        "From: sender@example.com\r\n" +
            "To: recipient@example.com\r\n" +
            "Subject: Hello from Aspire\r\n" +
            "\r\n" +
            "This email was captured by Mailpit.\r\n",
    )

    // Mailpit does not require authentication
    if err := smtp.SendMail(addr, nil, from, to, msg); err != nil {
        panic(err)
    }
}
```

:::note
The Go team has frozen `net/smtp` and accepts no new features. For new applications, you can pass the same `MAILPIT_HOST` and `MAILPIT_PORT` values to a maintained SMTP package.
:::

Use the `smtplib` module from the Python standard library — no third-party dependency is required:

```python title="app.py"
import os
import smtplib
from email.mime.text import MIMEText

# Read Aspire-injected SMTP connection properties
smtp_host = os.getenv("MAILPIT_HOST", "localhost")
smtp_port = int(os.getenv("MAILPIT_PORT", "1025"))

msg = MIMEText("This email was captured by Mailpit.")
msg["Subject"] = "Hello from Aspire"
msg["From"] = "sender@example.com"
msg["To"] = "recipient@example.com"

# Mailpit does not require authentication
with smtplib.SMTP(smtp_host, smtp_port) as server:
    server.sendmail("sender@example.com", ["recipient@example.com"], msg.as_string())
```

Install [`nodemailer`](https://nodemailer.com/), a popular SMTP client for Node.js:

```bash title="Terminal"
npm install nodemailer
npm install --save-dev @types/nodemailer
```

Read the injected environment variables and send an email:

```typescript title="index.ts"
import nodemailer from 'nodemailer';

// Read Aspire-injected SMTP connection properties
const transporter = nodemailer.createTransport({
  host: process.env.MAILPIT_HOST,
  port: Number(process.env.MAILPIT_PORT ?? 1025),
  secure: false, // Mailpit does not use TLS
  auth: undefined, // Mailpit does not require authentication
});

await transporter.sendMail({
  from: 'sender@example.com',
  to: 'recipient@example.com',
  subject: 'Hello from Aspire',
  text: 'This email was captured by Mailpit.',
});
```
**Tip:** If your app expects specific environment variable names different from the
  Aspire defaults, you can pass individual connection properties from the
  AppHost using `WithEnvironment`. See [Pass custom environment
  variables](/get-started/app-host/) in the AppHost reference.