Compare commits
7 commits
a88178c2ce
...
b4954163b2
Author | SHA1 | Date | |
---|---|---|---|
Julien Oculi | b4954163b2 | ||
Julien Oculi | b033031d39 | ||
Julien Oculi | 6659fe5ee6 | ||
Julien Oculi | cbb26e87ce | ||
Julien Oculi | 54ceae3e71 | ||
Julien Oculi | b437863f8b | ||
Julien Oculi | 6eaf3b6083 |
14
README.md
14
README.md
|
@ -8,6 +8,20 @@ Mail cli for Coh@bit.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
|
### From [jsr](https://jsr.io)
|
||||||
|
|
||||||
|
```sh
|
||||||
|
deno install \
|
||||||
|
--allow-read \
|
||||||
|
--allow-env \
|
||||||
|
--allow-net=0.0.0.0 \
|
||||||
|
--allow-sys=osRelease,networkInterfaces \
|
||||||
|
--allow-run=/usr/sbin/sendmail,whoami \
|
||||||
|
--global --force --name=cohamail jsr:@cohabit/mailer/cli
|
||||||
|
```
|
||||||
|
|
||||||
|
### From sources
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
>
|
>
|
||||||
> Currently bin manually added to [releases](./releases) tab. Prefer `git clone`
|
> Currently bin manually added to [releases](./releases) tab. Prefer `git clone`
|
||||||
|
|
20
cli.ts
20
cli.ts
|
@ -1,14 +1,34 @@
|
||||||
import config from './deno.json' with { type: 'json' }
|
import config from './deno.json' with { type: 'json' }
|
||||||
import { Command } from '@cliffy/command'
|
import { Command } from '@cliffy/command'
|
||||||
|
import { UpgradeCommand } from '@cliffy/command/upgrade'
|
||||||
|
import { JsrProvider } from '@cliffy/command/upgrade/provider/jsr'
|
||||||
import { cmd as send } from './cli/send.ts'
|
import { cmd as send } from './cli/send.ts'
|
||||||
import { cmd as preview } from './cli/preview.ts'
|
import { cmd as preview } from './cli/preview.ts'
|
||||||
|
|
||||||
|
const upgradeCommand = new UpgradeCommand({
|
||||||
|
args: [
|
||||||
|
'--allow-read',
|
||||||
|
'--allow-env',
|
||||||
|
'--allow-net=0.0.0.0',
|
||||||
|
'--allow-sys=osRelease,networkInterfaces',
|
||||||
|
'--allow-run=/usr/sbin/sendmail,whoami',
|
||||||
|
'--name=cohamail',
|
||||||
|
],
|
||||||
|
provider: [
|
||||||
|
new JsrProvider({
|
||||||
|
package: config.name as `@${string}/${string}`,
|
||||||
|
main: 'cli',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
const cli = new Command()
|
const cli = new Command()
|
||||||
.name('cohamail')
|
.name('cohamail')
|
||||||
.description('Mail cli for coh@bit.')
|
.description('Mail cli for coh@bit.')
|
||||||
.version(config.version)
|
.version(config.version)
|
||||||
.command('preview', preview)
|
.command('preview', preview)
|
||||||
.command('send', send)
|
.command('send', send)
|
||||||
|
.command('upgrade', upgradeCommand)
|
||||||
|
|
||||||
if (import.meta.main) {
|
if (import.meta.main) {
|
||||||
if (Deno.args.length) {
|
if (Deno.args.length) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@cohabit/mailer",
|
"name": "@cohabit/mailer",
|
||||||
"version": "0.2.1",
|
"version": "0.3.0",
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./mod.ts",
|
".": "./mod.ts",
|
||||||
"./cli": "./cli.ts",
|
"./cli": "./cli.ts",
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
"jsr:@std/cli@1.0.0-rc.2": "jsr:@std/cli@1.0.0-rc.2",
|
"jsr:@std/cli@1.0.0-rc.2": "jsr:@std/cli@1.0.0-rc.2",
|
||||||
"jsr:@std/encoding@1.0.0-rc.2": "jsr:@std/encoding@1.0.0-rc.2",
|
"jsr:@std/encoding@1.0.0-rc.2": "jsr:@std/encoding@1.0.0-rc.2",
|
||||||
"jsr:@std/fmt@~0.225.4": "jsr:@std/fmt@0.225.6",
|
"jsr:@std/fmt@~0.225.4": "jsr:@std/fmt@0.225.6",
|
||||||
|
"jsr:@std/io@~0.224.2": "jsr:@std/io@0.224.3",
|
||||||
"jsr:@std/path@1.0.0-rc.2": "jsr:@std/path@1.0.0-rc.2",
|
"jsr:@std/path@1.0.0-rc.2": "jsr:@std/path@1.0.0-rc.2",
|
||||||
"jsr:@std/path@^0.221.0": "jsr:@std/path@0.221.0",
|
"jsr:@std/path@^0.221.0": "jsr:@std/path@0.221.0",
|
||||||
"jsr:@std/text@1.0.0-rc.1": "jsr:@std/text@1.0.0-rc.1",
|
"jsr:@std/text@1.0.0-rc.1": "jsr:@std/text@1.0.0-rc.1",
|
||||||
|
@ -59,6 +60,7 @@
|
||||||
"jsr:@cliffy/keycode@1.0.0-rc.5",
|
"jsr:@cliffy/keycode@1.0.0-rc.5",
|
||||||
"jsr:@std/assert@1.0.0-rc.2",
|
"jsr:@std/assert@1.0.0-rc.2",
|
||||||
"jsr:@std/fmt@~0.225.4",
|
"jsr:@std/fmt@~0.225.4",
|
||||||
|
"jsr:@std/io@~0.224.2",
|
||||||
"jsr:@std/path@1.0.0-rc.2",
|
"jsr:@std/path@1.0.0-rc.2",
|
||||||
"jsr:@std/text@1.0.0-rc.1"
|
"jsr:@std/text@1.0.0-rc.1"
|
||||||
]
|
]
|
||||||
|
@ -84,6 +86,9 @@
|
||||||
"@std/fmt@0.225.6": {
|
"@std/fmt@0.225.6": {
|
||||||
"integrity": "aba6aea27f66813cecfd9484e074a9e9845782ab0685c030e453a8a70b37afc8"
|
"integrity": "aba6aea27f66813cecfd9484e074a9e9845782ab0685c030e453a8a70b37afc8"
|
||||||
},
|
},
|
||||||
|
"@std/io@0.224.3": {
|
||||||
|
"integrity": "b402edeb99c6b3778d9ae3e9927bc9085b170b41e5a09bbb7064ab2ee394ae2f"
|
||||||
|
},
|
||||||
"@std/path@0.221.0": {
|
"@std/path@0.221.0": {
|
||||||
"integrity": "0a36f6b17314ef653a3a1649740cc8db51b25a133ecfe838f20b79a56ebe0095",
|
"integrity": "0a36f6b17314ef653a3a1649740cc8db51b25a133ecfe838f20b79a56ebe0095",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
import accounts from '../config/account.json' with { type: 'json' }
|
import accounts from '../config/account.json' with { type: 'json' }
|
||||||
import dkim from '../config/dkim.json' with { type: 'json' }
|
import dkim from '../config/dkim.json' with { type: 'json' }
|
||||||
|
|
||||||
|
export type AddressString = `${string}@${string}.${string}`
|
||||||
|
|
||||||
export class Contact {
|
export class Contact {
|
||||||
#name: string
|
#name: string
|
||||||
#address: `${string}@${string}.${string}`
|
#address: AddressString
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
{ name, address }: {
|
{ name, address }: {
|
||||||
name: string
|
name: string
|
||||||
address: `${string}@${string}.${string}`
|
address: AddressString
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
this.#name = name
|
this.#name = name
|
||||||
|
@ -60,18 +62,18 @@ export class Contact {
|
||||||
return `${this.#name} <${this.#address}>`
|
return `${this.#name} <${this.#address}>`
|
||||||
}
|
}
|
||||||
|
|
||||||
toJSON() {
|
toJSON(): { name: string; address: AddressString } {
|
||||||
return {
|
return {
|
||||||
name: this.#name,
|
name: this.#name,
|
||||||
address: this.#address,
|
address: this.#address,
|
||||||
} as const
|
} as const
|
||||||
}
|
}
|
||||||
|
|
||||||
get name() {
|
get name(): string {
|
||||||
return this.#name
|
return this.#name
|
||||||
}
|
}
|
||||||
|
|
||||||
get address() {
|
get address(): AddressString {
|
||||||
return this.#address
|
return this.#address
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
|
import type SendmailTransport from 'npm:@types/nodemailer'
|
||||||
import type { Mail } from '../types.ts'
|
import type { Mail } from '../types.ts'
|
||||||
import { renderTemplate } from './template.tsx'
|
import { renderTemplate } from './template.tsx'
|
||||||
import { transporter } from './transporter.ts'
|
import { transporter } from './transporter.ts'
|
||||||
|
|
||||||
export async function send(mail: Mail) {
|
export async function send(
|
||||||
|
mail: Mail,
|
||||||
|
): Promise<SendmailTransport.SentMessageInfo> {
|
||||||
const { html, text } = await renderTemplate(mail.body)
|
const { html, text } = await renderTemplate(mail.body)
|
||||||
|
|
||||||
return (await transporter()).sendMail({
|
return (await transporter()).sendMail({
|
||||||
|
|
|
@ -4,6 +4,8 @@ import { render } from 'jsx-email'
|
||||||
import Turndown from 'turndown'
|
import Turndown from 'turndown'
|
||||||
import type { JSX } from 'preact'
|
import type { JSX } from 'preact'
|
||||||
|
|
||||||
|
console.assert(React !== undefined)
|
||||||
|
|
||||||
const htmlToMd = new Turndown({
|
const htmlToMd = new Turndown({
|
||||||
headingStyle: 'atx',
|
headingStyle: 'atx',
|
||||||
codeBlockStyle: 'fenced',
|
codeBlockStyle: 'fenced',
|
||||||
|
|
|
@ -28,7 +28,7 @@ function MagicLink(
|
||||||
ip?: string
|
ip?: string
|
||||||
endpoint: string
|
endpoint: string
|
||||||
},
|
},
|
||||||
) {
|
): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Html lang='fr' style={{ fontSize: '14px' }}>
|
<Html lang='fr' style={{ fontSize: '14px' }}>
|
||||||
<BaseStyle />
|
<BaseStyle />
|
||||||
|
|
|
@ -2,10 +2,11 @@ import { Body, Container, Html, Markdown, Preview } from 'jsx-email'
|
||||||
import { Signature } from './components/Signature.tsx'
|
import { Signature } from './components/Signature.tsx'
|
||||||
import type { Template } from '../types.ts'
|
import type { Template } from '../types.ts'
|
||||||
import { BaseStyle, bodyCss, messageCss, textCss } from './styles/base.tsx'
|
import { BaseStyle, bodyCss, messageCss, textCss } from './styles/base.tsx'
|
||||||
|
import type { JSX } from 'preact'
|
||||||
|
|
||||||
function Message(
|
function Message(
|
||||||
{ summary, body }: { summary?: string; body: string },
|
{ summary, body }: { summary?: string; body: string },
|
||||||
) {
|
): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Html lang='fr' style={{ fontSize: '14px' }}>
|
<Html lang='fr' style={{ fontSize: '14px' }}>
|
||||||
<BaseStyle />
|
<BaseStyle />
|
||||||
|
|
|
@ -29,7 +29,7 @@ function Welcome(
|
||||||
login: string
|
login: string
|
||||||
endpoint?: string
|
endpoint?: string
|
||||||
},
|
},
|
||||||
) {
|
): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Html lang='fr' style={{ fontSize: '14px' }}>
|
<Html lang='fr' style={{ fontSize: '14px' }}>
|
||||||
<BaseStyle />
|
<BaseStyle />
|
||||||
|
|
Loading…
Reference in a new issue