This commit is contained in:
davidontop 2024-05-21 06:50:03 +02:00
commit a931dc8d28
Signed by: DavidOnTop
GPG key ID: 5D05538A45D5149F
14 changed files with 670 additions and 0 deletions

25
.editorconfig Normal file
View file

@ -0,0 +1,25 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
indent_style = tab
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
[*.{yml,yaml}]
indent_style = space
indent_size = 2
[*.fs]
indent_style = space
indent_size = 4
fsharp_newline_between_type_definition_and_members=true
fsharp_multiline_bracket_style=aligned
fsharp_keep_max_number_of_blank_lines=1
fsharp_multiline_bracket_style = stroustrup
[*.fsi]
fsharp_newline_between_type_definition_and_members=true
fsharp_keep_max_number_of_blank_lines=1

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
/target
bin
obj

11
.rustfmt.toml Normal file
View file

@ -0,0 +1,11 @@
condense_wildcard_suffixes = true
edition = "2021"
fn_single_line = true
format_code_in_doc_comments = true
format_macro_matchers = true
hard_tabs = true
match_block_trailing_comma = true
imports_granularity = "Crate"
newline_style = "Unix"
group_imports = "StdExternalCrate"
tab_spaces = 4

39
Cargo.toml Normal file
View file

@ -0,0 +1,39 @@
[package]
name = "iomail-server"
version = "0.1.0"
edition = "2021"
description = "iomail"
authors = ["davidontop <me@davidon.top>"]
readme = "README.md"
documentation = "https://docs.rs/iomail"
license = "GLWTPL"
repository = "git@github.com:davidontop/iomail.git"
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
tracing = "0.1"
tracing-subscriber = "0.3"
tokio = { version = "1.0", features = ["full"] }
[profile.release]
codegen-units = 1
lto = true
opt-level = 'z'
[[workspace.metadata.leptos]]
name = "iomail"
bin-package = "server"
lib-package = "client"
site-root = "target/site"
site-pkg-dir = "pkg"
style-file = "client/globaltw.css"
assets-dir = "public"
site-addr = "127.0.0.1:8690"
reload-port = 3001
watch = false
env = "DEV"
bin-features = []
bin-default-features = false
lib-features = []
lib-default-features = false

26
LICENSE Normal file
View file

@ -0,0 +1,26 @@
GLWTS(Good Luck With That Shit) Public License
Copyright (c) Every-fucking-one
Everyone is permitted to copy, distribute, modify, merge, sell, publish,
sublicense or whatever the fuck they want with this software but at their
OWN RISK.
Preamble
The author has absolutely no fucking clue what the code in this project
does. It might just fucking work or not, there is no third option.
GOOD LUCK WITH THAT SHIT PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION, AND MODIFICATION
0. You just DO WHATEVER THE FUCK YOU WANT TO as long as you NEVER LEAVE
A FUCKING TRACE TO TRACK THE AUTHOR of the original product to blame for
or held responsible.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
Good luck and Godspeed.

1
README.md Normal file
View file

@ -0,0 +1 @@
# iomail

6
app/Cargo.toml Normal file
View file

@ -0,0 +1,6 @@
[package]
name = "app"
version = "0.1.0"
edition = "2021"
[dependencies]

14
app/src/lib.rs Normal file
View file

@ -0,0 +1,14 @@
pub fn add(left: usize, right: usize) -> usize {
left + right
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let result = add(2, 2);
assert_eq!(result, 4);
}
}

400
pgmodeler.dbm Normal file
View file

@ -0,0 +1,400 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
CAUTION: Do not modify this file unless you know what you are doing.
Unexpected results may occur if the code is changed deliberately.
-->
<dbmodel pgmodeler-ver="1.1.3" use-changelog="false" max-obj-count="12"
last-position="0,137" last-zoom="1"
default-owner="postgres"
layers="Default layer"
active-layers="0"
layer-name-colors="#000000"
layer-rect-colors="#b4b4b4"
show-layer-names="false" show-layer-rects="false">
<database name="iomail" is-template="false" allow-conns="true">
</database>
<schema name="public" layers="0" fill-color="#e1e1e1" name-color="#000000" sql-disabled="true">
</schema>
<table name="Grant" layers="0" collapse-mode="2" max-obj-count="4" z-value="0">
<schema name="public"/>
<role name="postgres"/>
<position x="160" y="240"/>
<column name="Id" not-null="true">
<type name="bytea" length="0"/>
</column>
<column name="Resource" not-null="true">
<type name="bytea" length="0"/>
</column>
<column name="Permission" not-null="true">
<type name="integer" length="0"/>
</column>
<column name="GrantedTo" not-null="true">
<type name="bigint" length="0"/>
</column>
<constraint name="Grant_pk" type="pk-constr" table="public.&quot;Grant&quot;">
<columns names="Id" ref-type="src-columns"/>
</constraint>
</table>
<table name="Project" layers="0" collapse-mode="2" max-obj-count="3" z-value="0">
<schema name="public"/>
<role name="postgres"/>
<position x="480" y="260"/>
<column name="Id" not-null="true">
<type name="bytea" length="0"/>
</column>
<column name="Name" not-null="true">
<type name="varchar" length="0"/>
</column>
<column name="Description" not-null="true">
<type name="varchar" length="0"/>
</column>
<constraint name="Project_pk" type="pk-constr" table="public.&quot;Project&quot;">
<columns names="Id" ref-type="src-columns"/>
</constraint>
</table>
<extension name="hstore">
<schema name="public"/>
<type name="hstore"/>
</extension>
<table name="Mail" layers="0" collapse-mode="2" max-obj-count="7" z-value="0">
<schema name="public"/>
<role name="postgres"/>
<position x="760" y="280"/>
<column name="Id" not-null="true">
<type name="bytea" length="0"/>
</column>
<column name="From" not-null="true">
<type name="varchar" length="0"/>
</column>
<column name="To" not-null="true">
<type name="varchar" length="0" dimension="1"/>
</column>
<column name="Properties" not-null="true">
<type name="public.hstore" length="0"/>
</column>
<column name="Body" not-null="true">
<type name="bytea" length="0"/>
</column>
<constraint name="Mail_pk" type="pk-constr" table="public.&quot;Mail&quot;">
<columns names="Id" ref-type="src-columns"/>
</constraint>
<customidxs object-type="column">
<object name="Lists" index="5"/>
</customidxs>
<customidxs object-type="constraint">
<object name="Lists_fk" index="1"/>
</customidxs></table>
<table name="Lists" layers="0" collapse-mode="2" max-obj-count="6" z-value="0">
<schema name="public"/>
<role name="postgres"/>
<position x="160" y="620"/>
<column name="Id" not-null="true">
<type name="bytea" length="0"/>
</column>
<column name="Name" not-null="true">
<type name="varchar" length="0"/>
</column>
<column name="Description" not-null="true">
<type name="varchar" length="0"/>
</column>
<column name="Mail" not-null="true">
<type name="varchar" length="0"/>
</column>
<constraint name="List_pk" type="pk-constr" table="public.&quot;Lists&quot;">
<columns names="Id" ref-type="src-columns"/>
</constraint>
<constraint name="Unique Mail" type="uq-constr" table="public.&quot;Lists&quot;">
<columns names="Mail" ref-type="src-columns"/>
</constraint>
<customidxs object-type="column">
<object name="Project" index="3"/>
</customidxs>
<customidxs object-type="constraint">
<object name="Project_fk" index="1"/>
</customidxs></table>
<relationship name="List_has_many_Mails" type="rel1n" layers="0"
src-col-pattern="{st}"
pk-pattern="{dt}_pk" uq-pattern="{dt}_uq"
src-fk-pattern="{st}_fk"
custom-color="#254479"
src-table="public.&quot;Lists&quot;"
dst-table="public.&quot;Mail&quot;"
src-required="true" dst-required="false"/>
<relationship name="Project_has_many_List" type="rel1n" layers="0"
src-col-pattern="{st}"
pk-pattern="{dt}_pk" uq-pattern="{dt}_uq"
src-fk-pattern="{st}_fk"
custom-color="#ced88f"
src-table="public.&quot;Project&quot;"
dst-table="public.&quot;Lists&quot;"
src-required="true" dst-required="false"/>
<table name="Board" layers="0" collapse-mode="2" max-obj-count="4" z-value="0">
<schema name="public"/>
<role name="postgres"/>
<position x="520" y="660"/>
<column name="Id" not-null="true">
<type name="bytea" length="0"/>
</column>
<column name="Name" not-null="true">
<type name="varchar" length="0"/>
</column>
<column name="Description" not-null="true">
<type name="varchar" length="0"/>
</column>
<constraint name="Board_pk" type="pk-constr" table="public.&quot;Board&quot;">
<columns names="Id" ref-type="src-columns"/>
</constraint>
<customidxs object-type="column">
<object name="Project" index="3"/>
</customidxs>
<customidxs object-type="constraint">
<object name="Project_fk" index="1"/>
</customidxs></table>
<relationship name="Project_has_many_Boards" type="rel1n" layers="0"
src-col-pattern="{st}"
pk-pattern="{dt}_pk" uq-pattern="{dt}_uq"
src-fk-pattern="{st}_fk"
custom-color="#47e6ba"
src-table="public.&quot;Project&quot;"
dst-table="public.&quot;Board&quot;"
src-required="true" dst-required="false"/>
<table name="Issue" layers="0" collapse-mode="2" max-obj-count="2" z-value="0">
<schema name="public"/>
<role name="postgres"/>
<position x="900" y="560"/>
<column name="Id" not-null="true">
<type name="bytea" length="0"/>
</column>
<constraint name="Issue_pk" type="pk-constr" table="public.&quot;Issue&quot;">
<columns names="Id" ref-type="src-columns"/>
</constraint>
<customidxs object-type="column">
<object name="Board" index="1"/>
</customidxs>
<customidxs object-type="constraint">
<object name="Board_fk" index="1"/>
</customidxs></table>
<relationship name="Board_has_many_Issues" type="rel1n" layers="0"
src-col-pattern="{st}"
pk-pattern="{dt}_pk" uq-pattern="{dt}_uq"
src-fk-pattern="{st}_fk"
custom-color="#1e54c7"
src-table="public.&quot;Board&quot;"
dst-table="public.&quot;Issue&quot;"
src-required="true" dst-required="false"/>
<table name="IssueField" layers="0" collapse-mode="2" max-obj-count="6" z-value="0">
<schema name="public"/>
<role name="postgres"/>
<position x="1020" y="800"/>
<column name="Id" not-null="true">
<type name="bytea" length="0"/>
</column>
<column name="Type" not-null="true">
<type name="smallint" length="0"/>
</column>
<column name="Opts" not-null="true">
<type name="smallint" length="0"/>
</column>
<column name="Default">
<type name="bytea" length="0"/>
</column>
<constraint name="IssueField_pk" type="pk-constr" table="public.&quot;IssueField&quot;">
<columns names="Id" ref-type="src-columns"/>
</constraint>
<customidxs object-type="column">
<object name="Board" index="4"/>
</customidxs>
<customidxs object-type="constraint">
<object name="Board_fk" index="1"/>
</customidxs></table>
<relationship name="Board_has_many_IssueField" type="rel1n" layers="0"
src-col-pattern="{st}"
pk-pattern="{dt}_pk" uq-pattern="{dt}_uq"
src-fk-pattern="{st}_fk"
custom-color="#3d6105"
src-table="public.&quot;Board&quot;"
dst-table="public.&quot;IssueField&quot;"
src-required="true" dst-required="false"/>
<table name="IssueData" layers="0" collapse-mode="2" max-obj-count="4" z-value="0">
<schema name="public"/>
<role name="postgres"/>
<position x="1280" y="480"/>
<column name="Id" not-null="true">
<type name="bytea" length="0"/>
</column>
<column name="Data">
<type name="bytea" length="0"/>
</column>
<constraint name="IssueData_pk" type="pk-constr" table="public.&quot;IssueData&quot;">
<columns names="Id" ref-type="src-columns"/>
</constraint>
<customidxs object-type="column">
<object name="Field" index="3"/>
<object name="Issue" index="2"/>
</customidxs>
<customidxs object-type="constraint">
<object name="IssueField_fk" index="2"/>
<object name="Issue_fk" index="1"/>
</customidxs></table>
<relationship name="Issue_has_many_IssueData" type="rel1n" layers="0"
src-col-pattern="Issue"
pk-pattern="{dt}_pk" uq-pattern="{dt}_uq"
src-fk-pattern="{st}_fk"
custom-color="#60ecee"
src-table="public.&quot;Issue&quot;"
dst-table="public.&quot;IssueData&quot;"
src-required="true" dst-required="false"/>
<relationship name="IssueField_has_many_IssueData" type="rel1n" layers="0"
src-col-pattern="Field"
pk-pattern="{dt}_pk" uq-pattern="{dt}_uq"
src-fk-pattern="{st}_fk"
custom-color="#19f273"
src-table="public.&quot;IssueField&quot;"
dst-table="public.&quot;IssueData&quot;"
src-required="true" dst-required="false"/>
<table name="PermissionPreset" layers="0" collapse-mode="2" max-obj-count="3" z-value="0">
<schema name="public"/>
<role name="postgres"/>
<position x="1080" y="300"/>
<column name="Id" not-null="true">
<type name="bytea" length="0"/>
</column>
<column name="Name" not-null="true">
<type name="varchar" length="0"/>
</column>
<column name="Permission" not-null="true">
<type name="integer" length="0"/>
</column>
<constraint name="PermissionPreset_pk" type="pk-constr" table="public.&quot;PermissionPreset&quot;">
<columns names="Id" ref-type="src-columns"/>
</constraint>
</table>
<table name="SuperAdmins" layers="0" collapse-mode="2" max-obj-count="2" z-value="0">
<schema name="public"/>
<role name="postgres"/>
<position x="520" y="900"/>
<column name="Id" not-null="true">
<type name="bytea" length="0"/>
</column>
<column name="User" not-null="true">
<type name="bigint" length="0"/>
</column>
<constraint name="SuperAdmins_pk" type="pk-constr" table="public.&quot;SuperAdmins&quot;">
<columns names="Id" ref-type="src-columns"/>
</constraint>
</table>
<index name="Resource" table="public.&quot;Grant&quot;"
concurrent="false" unique="false" fast-update="false" buffering="false" nulls-not-distinct="false"
index-type="btree" factor="0">
<idxelement use-sorting="false">
<column name="Resource"/>
</idxelement>
</index>
<index name="User" table="public.&quot;Grant&quot;"
concurrent="false" unique="false" fast-update="false" buffering="false" nulls-not-distinct="false"
index-type="btree" factor="0">
<idxelement use-sorting="false">
<column name="GrantedTo"/>
</idxelement>
</index>
<index name="Name" table="public.&quot;Project&quot;"
concurrent="false" unique="false" fast-update="false" buffering="false" nulls-not-distinct="false"
index-type="btree" factor="0">
<idxelement use-sorting="false">
<column name="Name"/>
</idxelement>
</index>
<index name="Project_1" table="public.&quot;Lists&quot;"
concurrent="false" unique="false" fast-update="false" buffering="false" nulls-not-distinct="false"
index-type="btree" factor="0">
<idxelement use-sorting="false">
<column name="Project"/>
</idxelement>
</index>
<index name="Project_2" table="public.&quot;Board&quot;"
concurrent="false" unique="false" fast-update="false" buffering="false" nulls-not-distinct="false"
index-type="btree" factor="0">
<idxelement use-sorting="false">
<column name="Project"/>
</idxelement>
</index>
<index name="User_1" table="public.&quot;SuperAdmins&quot;"
concurrent="false" unique="false" fast-update="false" buffering="false" nulls-not-distinct="false"
index-type="btree" factor="0">
<idxelement use-sorting="false">
<column name="User"/>
</idxelement>
</index>
<index name="List_1" table="public.&quot;Mail&quot;"
concurrent="false" unique="false" fast-update="false" buffering="false" nulls-not-distinct="false"
index-type="btree" factor="0">
<idxelement use-sorting="false">
<column name="Lists"/>
</idxelement>
</index>
<index name="Board_1" table="public.&quot;Issue&quot;"
concurrent="false" unique="false" fast-update="false" buffering="false" nulls-not-distinct="false"
index-type="btree" factor="0">
<idxelement use-sorting="false">
<column name="Board"/>
</idxelement>
</index>
<index name="Board_2" table="public.&quot;IssueField&quot;"
concurrent="false" unique="false" fast-update="false" buffering="false" nulls-not-distinct="false"
index-type="btree" factor="0">
<idxelement use-sorting="false">
<column name="Board"/>
</idxelement>
</index>
<index name="Issue_1" table="public.&quot;IssueData&quot;"
concurrent="false" unique="false" fast-update="false" buffering="false" nulls-not-distinct="false"
index-type="btree" factor="0">
<idxelement use-sorting="false">
<column name="Issue"/>
</idxelement>
</index>
<index name="Mail_1" table="public.&quot;Lists&quot;"
concurrent="false" unique="false" fast-update="false" buffering="false" nulls-not-distinct="false"
index-type="btree" factor="0">
<idxelement use-sorting="false">
<column name="Mail"/>
</idxelement>
</index>
</dbmodel>

0
server/Cargo.toml Normal file
View file

3
server/src/main.rs Normal file
View file

@ -0,0 +1,3 @@
fn main() {
println!("Hello, world!");
}

9
smtp/go.mod Normal file
View file

@ -0,0 +1,9 @@
module git.davidon.top/iomail.git
go 1.22.3
require (
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 // indirect
github.com/emersion/go-smtp v0.21.2 // indirect
github.com/rabbitmq/amqp091-go v1.10.0 // indirect
)

6
smtp/go.sum Normal file
View file

@ -0,0 +1,6 @@
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21 h1:OJyUGMJTzHTd1XQp98QTaHernxMYzRaOasRir9hUlFQ=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-smtp v0.21.2 h1:OLDgvZKuofk4em9fT5tFG5j4jE1/hXnX75UMvcrL4AA=
github.com/emersion/go-smtp v0.21.2/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
github.com/rabbitmq/amqp091-go v1.10.0 h1:STpn5XsHlHGcecLmMFCtg7mqq0RnD+zFr4uzukfVhBw=
github.com/rabbitmq/amqp091-go v1.10.0/go.mod h1:Hy4jKW5kQART1u+JkDTF9YYOQUHXqMuhrgxOEeS7G4o=

127
smtp/main.go Normal file
View file

@ -0,0 +1,127 @@
package main
import (
"bytes"
"encoding/base64"
"encoding/json"
"io"
"log"
"os"
"github.com/emersion/go-smtp"
"github.com/rabbitmq/amqp091-go"
)
type Mail struct {
From *string `json:"from"`
To *string `json:"to"`
Body *string `json:"body"`
UTF8 *bool `json:"UTF8"`
}
type backend struct{
Queue *amqp091.Queue
Channel *amqp091.Channel
}
func (bkd *backend) NewSession(c *smtp.Conn) (smtp.Session, error) {
return &session{
Queue: bkd.Queue,
Channel: bkd.Channel,
MailBuilder: Mail{},
}, nil
}
type session struct{
Queue *amqp091.Queue
MailBuilder Mail
Channel *amqp091.Channel
}
func (s *session) AuthPlain(username, password string) error {
return nil
}
func (s *session) Mail(from string, opts *smtp.MailOptions) error {
s.MailBuilder.From = &from
s.MailBuilder.UTF8 = &opts.UTF8
return nil
}
func (s *session) Rcpt(to string, opts *smtp.RcptOptions) error {
s.MailBuilder.To = &to
return nil
}
func (s *session) Data(r io.Reader) error {
buf := new(bytes.Buffer)
if _, err := buf.ReadFrom(r); err != nil {
log.Fatal(err)
}
body := base64.StdEncoding.EncodeToString(buf.Bytes())
s.MailBuilder.Body = &body
return nil
}
func (s *session) Reset() {
submitMail(s.MailBuilder, s.Channel, s.Queue)
}
func (s *session) Logout() error {
return nil
}
func submitMail(mail Mail, ch *amqp091.Channel, q *amqp091.Queue) {
mb, err := json.Marshal(mail)
if err != nil {
log.Fatal(err)
}
err = ch.Publish(
"",
q.Name,
false,
false,
amqp091.Publishing{
ContentType: "application/octet-stream",
Body: []byte(base64.StdEncoding.EncodeToString(mb)),
},
)
if err != nil {
log.Println("oh uh")
log.Fatal(err)
}
log.Println("Submited mail to rabbitmq")
}
func main() {
conn, err := amqp091.Dial("amqp://d:8o9HGX!CFx!2sg!@dUqN@localhost:5672/")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
ch, err := conn.Channel()
if err != nil {
log.Fatal(err)
}
defer ch.Close()
q, err := ch.QueueDeclare("mail", true, false, false, false, nil)
if err != nil {
log.Fatal(err)
}
s := smtp.NewServer(&backend{
Queue: &q,
Channel: ch,
})
s.Addr = "0.0.0.0:8700"
s.AllowInsecureAuth = true
s.Debug = os.Stderr
log.Println("Starting smtp server")
log.Fatal(s.ListenAndServe())
}