IHP provides email functionality via the ihp-mail package, built on top of mime-mail.
Setup
Add ihp-mail to your flake.nix:
haskellPackages = p: with p; [
p.ihp
cabal-install
base
wai
ihp-mail # Add this
];
Rebuild with devenv up or restart the development server.
Generating Email Templates
Open the Mail Code Generator
Access it from the IHP development tools.
Select controller and name
Choose the controller (e.g., Users) and enter the mail name (e.g., Confirmation).
Generate the template
Click Preview, then Generate to create Web/Mail/Users/Confirmation.hs.
Generated template:
module Web.Mail.Users.Confirmation where
import Web.View.Prelude
import IHP.MailPrelude
data ConfirmationMail = ConfirmationMail { user :: User }
instance BuildMail ConfirmationMail where
subject = "Subject"
to ConfirmationMail { .. } = Address {
addressName = Just "F L",
addressEmail = "[email protected]"
}
from = "[email protected]"
html ConfirmationMail { .. } = [hsx|
Hello World
|]
Customizing Email Templates
Subject Line
subject = "Confirm your Account"
Recipient
Use user data:
to ConfirmationMail { .. } = Address {
addressName = Just user.name,
addressEmail = user.email
}
Sender
Reply-To Address
replyTo ConfirmationMail { .. } = Just Address {
addressName = Just "Support",
addressEmail = "[email protected]"
}
Email Content
HTML version:
html ConfirmationMail { .. } = [hsx|
Hey {user.name}, <br/>
Thanks for signing up! Please confirm your account by following this link: <br/>
<a href={urlTo ConfirmUserAction}>Confirm Account</a>
|]
Plain text version (recommended):
text ConfirmationMail { .. } = cs [trimming|
Hey ${userName},
Thanks for signing up! Please confirm your account by following this link:
https://example.com/confirm
|]
where
userName = user.name
Providing a plain text version improves deliverability and accessibility. If omitted, IHP auto-generates one by stripping HTML tags.
Sending Emails
From a controller or script:
import IHP.Mail (sendMail)
action MyAction = do
user <- fetch "..."
sendMail ConfirmationMail { user }
Mail Server Configuration
Configure in Config/Config.hs:
Local Sendmail
import IHP.Mail.Types
config :: ConfigBuilder
config = do
option Development
option Sendmail
SMTP
import IHP.Mail.Types
config :: ConfigBuilder
config = do
option $ SMTP
{ host = "smtp.myisp.com"
, port = 2525
, credentials = Just ("myusername", "hunter2")
, encryption = TLS -- or: Unencrypted, STARTTLS
}
Environment Variables for SMTP
Recommended for production:
import IHP.Mail.Types
import Network.Socket (PortNumber)
import IHP.EnvVar
config :: ConfigBuilder
config = do
smtpHost <- env @Text "SMTP_HOST"
smtpPort <- env @PortNumber "SMTP_PORT"
smtpEncryption <- env @SMTPEncryption "SMTP_ENCRYPTION"
smtpUserMaybe <- envOrNothing "SMTP_USER"
smtpPasswordMaybe <- envOrNothing "SMTP_PASSWORD"
let smtpCredentials = case (smtpUserMaybe, smtpPasswordMaybe) of
(Just user, Just password) -> Just (user, password)
_ -> Nothing
option $ SMTP
{ host = cs smtpHost
, port = smtpPort
, credentials = smtpCredentials
, encryption = smtpEncryption
}
In .envrc:
export SMTP_HOST="127.0.0.1"
export SMTP_PORT="1025"
export SMTP_ENCRYPTION="Unencrypted"
export SMTP_USER="username"
export SMTP_PASSWORD="password"
AWS SES
import IHP.Mail.Types
config :: ConfigBuilder
config = do
option $ SES
{ accessKey = "YOUR_AWS_ACCESS_KEY"
, secretKey = "YOUR_AWS_SECRET_KEY"
, region = "eu-west-1"
}
SendGrid
import IHP.Mail.Types
config :: ConfigBuilder
config = do
option $ SendGrid
{ apiKey = "YOUR_SENDGRID_API_KEY"
, category = Nothing -- or: Just "mailcategory"
}
MailHog (Development)
MailHog captures outgoing emails for testing:
- Install and run MailHog
- Configure SMTP to point to MailHog (default:
127.0.0.1:1025)
- View emails at
http://0.0.0.0:8025/
# .envrc
export SMTP_HOST="127.0.0.1"
export SMTP_PORT="1025"
export SMTP_ENCRYPTION="Unencrypted"
Advanced Features
headers ConfirmationMail { .. } =
[ ("X-Mailer", "IHP Application")
, ("In-Reply-To", "<[email protected]>")
]
Email Attachments
instance BuildMail ConfirmationMail where
subject = "Your Receipt"
to ConfirmationMail { .. } = Address {
addressName = Just user.name,
addressEmail = user.email
}
from = "[email protected]"
html ConfirmationMail { .. } = [hsx|
Please find your receipt attached.
|]
attachments ConfirmationMail { .. } = [
MailAttachment {
name = "receipt.pdf",
contentType = "application/pdf",
content = pdfContent
}
]
Remember to configure SPF and DKIM records for your domain to ensure reliable email delivery.