Skip to content

Commit

Permalink
Merge branch 'master' of github.com:digitallyinduced/ihp
Browse files Browse the repository at this point in the history
  • Loading branch information
mpscholten committed Dec 21, 2021
2 parents 8d210d4 + 494db5b commit 16b6510
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 16 deletions.
4 changes: 2 additions & 2 deletions Guide/helpful-tips.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ In general the `\case ...` can be expanded to `\value -> case value of ...`.

### The Pipe operator [`|>`](https://ihp.digitallyinduced.com/api-docs/IHP-HaskellSupport.html#v:-124--62-)

In IHP code bases you find lot's of usage of the [`|>`](https://ihp.digitallyinduced.com/api-docs/IHP-HaskellSupport.html#v:-124--62-) operator. We usually call it the `pipe operator`.
In IHP code bases you find lots of usage of the [`|>`](https://ihp.digitallyinduced.com/api-docs/IHP-HaskellSupport.html#v:-124--62-) operator. We usually call it the `pipe operator`.

The operator allows you to write code like this:

Expand All @@ -147,7 +147,7 @@ validateField #firstname nonEmpty (

In general:
```haskell
function arg1 arg2 object
function arg1 arg2 object
=
object |> function arg1 arg2
```
Expand Down
3 changes: 1 addition & 2 deletions Guide/ihp-pro.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ With bugs we have the same story. Instead of just a GitHub issue, it’s now a c

Here’s the big plan in a short form:

1. Introduce a IHP Pro subscription
1. Introduce an IHP Pro subscription
2. Use the funding by our new customers to make IHP & the ecosystem a lot better
3. Become the well-known best framework for building web applications

Expand All @@ -46,4 +46,3 @@ We recommend you try out these features after upgrading to pro:

- [Google Login](oauth.html#introduction)
- [Email Confirmation](authentication.html#email-confirmation)

56 changes: 51 additions & 5 deletions Guide/mail.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ instance BuildMail ConfirmationMail where
|]
```

### Changing Subject
### Changing the Subject

Let's first change the subject of our mail from `Subject` to something more useful:

Expand Down Expand Up @@ -66,9 +66,17 @@ to ConfirmationMail { .. } = Address { addressName = Just (get #name user), addr

The email sender is set to `hi@example.com` by default. Usually, you want to use your domain here. For this example, we will stick with the `hi@example.com` for now.

### Changing the Reply-To address

By default the "Reply" button in an email programs creates a reply to the From address. You can change that behavior by setting the `Reply-To` header to another target email address:

```haskell
replyTo ConfirmationMail { .. } = Just Address { addessName = Just "Support", addressEmail = "support@example.com" }
```

### Email Content

Last we need to change the email text a little bit. The mail supports HSX so this is similar to writing a IHP view:
Last we need to change the email text a little bit. The mail supports HSX so this is similar to writing an IHP view:

```haskell
html ConfirmationMail { .. } = [hsx|
Expand All @@ -87,6 +95,21 @@ action MyAction = do
sendMail ConfirmationMail { user }
```

## Custom Headers

If you need to send specific mail headers you can do so as well:

```haskell
headers ConfirmationMail { .. } =
[ ("X-Mailer", "mail4j 2.17.0")
, ("In-Reply-To", "<123456@list.example.com>")
]
```

Implementation detail: IHP first adds headers set by itself (like `Subject` and the optional `Reply-To`), then headers provided via `headers`. If you don't want to use the `replyTo` helper from above it's absolutely fine to add the `Reply-To` header manually.



## Mail Servers

By default, IHP uses your local `sendmail` to send out the email. IHP also supports sending mail via AWS Simple Email Service (SES), SendGrid (via Azure or directly) or via any standard SMTP server.
Expand All @@ -107,13 +130,14 @@ config = do
option $ SMTP
{ host = "smtp.myisp.com"
, port = 2525
, credentials = Nothing -- or Just ("myusername","hunter2")
, credentials = Nothing -- or: Just ("myusername","hunter2")
, encryption = TLS -- <-- other options: `Unencrypted` or `STARTTLS`
}
```

### Local (For Debugging)

A convinient way to see sent mails is to use a local mail testing such as [MailHog](https://github.com/mailhog/MailHog). This service will catch all outgoing emails, and show their HTML to you - which is handy while developing.
A convinient way to see sent mails is to use a local mail testing such as [MailHog](https://github.com/mailhog/MailHog). This service will catch all outgoing emails, and show their HTML to you - which is handy while developing.

1. Make sure `sendmail` is locally installed and configured.
2. Install MailHog.
Expand All @@ -133,6 +157,7 @@ config = do
{ host = "127.0.1.1"
, port = 1025
, credentials = Nothing
, encryption = Unencrypted
}
```

Expand Down Expand Up @@ -196,4 +221,25 @@ instance BuildMail ConfirmationMail where

## Plain Text Emails

TODO
Every email should have a plain text version for people with reasonable mail clients. If you don't specify one and only set the HTML content via `html` (see above), then IHP automatically creates a plain text version from you by stripping away all HTML tags. This is suboptimal.

The better option is to manually provide a useful plain text version of your emails:

```haskell
import NeatInterpolation

text ConfirmationMail { .. } = cs [trimming|
Hey ${userName},

Thanks for signing up! Please confirm your account by following this link:
https://....
|]
where
userName = get #name user
```

Note a few differences to the `html` version here:

- We use `[trimming| ... |]` instead of `[hsx| ... |]` so we can't use HSX's inline Haskell like `{get #userName user}` but have to live with simple substitution. Note the dollar sign in front of these substitutions: `${userName}`.
- The `[trimming||]` quasiquoter takes care of removing the whitespace that our indentations introduced, which we don't want in the actual emails.
- We use `cs` to convert the `[Char]` to the required `Text` type.
6 changes: 3 additions & 3 deletions Guide/recipes.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ To confirm before a link is fired add an `onclick` to the link.
To generate a random string which can be used as a secure token or hash use [`generateAuthenticationToken`](https://hackage.haskell.org/package/wreq):

```haskell
import IHP.AuthSupport.Authentication -- Not needed if you're inside a IHP controller
import IHP.AuthSupport.Authentication -- Not needed if you're inside an IHP controller

do
token <- generateAuthenticationToken
Expand Down Expand Up @@ -346,7 +346,7 @@ import Network.HTTP.Types.Header (hContentType)
import Network.HTTP.Types (status404)
import Network.Wai (responseLBS)

customNotFoundResponse :: (?context :: ControllerContext) => IO ()
customNotFoundResponse :: (?context :: ControllerContext) => IO ()
customNotFoundResponse = do
page <- LBS.readFile "static/404.html"
respondAndExit $ responseLBS status404 [(hContentType, "text/html")] page
Expand All @@ -356,7 +356,7 @@ Now you can use your `customNotFoundResponse`:

```haskell
action WelcomeAction = do
post <- fetchOneOrNothing ("30a73014-101e-4269-be91-be6c019de289" :: Id Post)
post <- fetchOneOrNothing ("30a73014-101e-4269-be91-be6c019de289" :: Id Post)
case post of
Nothing -> customNotFoundResponse -- Database record disappeared !!!
Just post -> render ShowView { .. }
Expand Down
6 changes: 3 additions & 3 deletions IHP/Mail.hs
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,11 @@ class BuildMail mail where
bcc :: (?context :: context, ConfigProvider context) => mail -> [Address]
bcc mail = []

-- | Custom headers, excluding `from`, `to`, `cc`, and `bcc`
-- | Custom headers, excluding @from@, @to@, @cc@, @bcc@, @subject@, and @reply-to@
--
-- __Example:__ Add a custom X-Sender header
-- __Example:__ Add a custom X-Mailer header
--
-- > headers CreateAccountMail { .. } = [("X-Sender", "mail4j 2.17.0")]
-- > headers CreateAccountMail { .. } = [("X-Mailer", "mail4j 2.17.0")]
--
headers :: (?context :: context, ConfigProvider context) => mail -> Headers
headers mail = []
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Auto Refresh can be enabled for IHP views with a single line of code.
[Watch it in action!](https://twitter.com/digitallyinduce/status/1312017800223956992)

**Longterm Roadmap**
Lot's of frameworks are already gone a year after launch. Especially in the fast moving JS world. But don't worry about IHP. We have been using it at digitally induced since 2017. It's actively used by us and our friends and partners. Even without external contributors we will build new features and do periodic maintenance releases in the future. We have big plans for IHP and as a profitable and independent software company we have the ability to actually execute them over the longterm.
Lots of frameworks are already gone a year after launch. Especially in the fast moving JS world. But don't worry about IHP. We have been using it at digitally induced since 2017. It's actively used by us and our friends and partners. Even without external contributors we will build new features and do periodic maintenance releases in the future. We have big plans for IHP and as a profitable and independent software company we have the ability to actually execute them over the longterm.

## Reviews

Expand Down

0 comments on commit 16b6510

Please sign in to comment.