commit fb77ab166443e8882652dfdbd580a6732494bfd8 from: Oliver Lowe date: Fri Mar 15 06:47:29 2024 UTC doc: document receiving and reading sections While here make apget print mail format by default, consistent with rest of system. commit - 6f092909c92185b689e43e27ae1e2603f6368834 commit + fb77ab166443e8882652dfdbd580a6732494bfd8 blob - 73956f3e3a51a165a2b1d0b3e72a058faf4b320e blob + bd413821ebd22baaffe03682a695100fe2bae3f5 --- cmd/apget/apget.go +++ cmd/apget/apget.go @@ -3,19 +3,19 @@ // // Its usage is: // -// apget [-m] url +// apget [-j] url // // The flags understood are: // -// -m -// Print the activity as a RFC5322 message. -// The default is indented JSON. +// -j +// Print the activity as indented JSON. +// The default is a RFC5322 message. // // # Examples // // Deliver a Mastodon post to a local user using apsend: // -// apget -m https://hachyderm.io/@otl/112093503066930591 | apsend otl +// apget https://hachyderm.io/@otl/112093503066930591 | apsend otl package main import ( @@ -27,14 +27,14 @@ import ( "olowe.co/apub" ) -var mflag bool +var jflag bool func init() { - flag.BoolVar(&mflag, "m", false, "format as mail") + flag.BoolVar(&jflag, "j", false, "format as json") flag.Parse() } -const usage = "apget [-m] url" +const usage = "apget [-j] url" func main() { if len(flag.Args()) != 1 { @@ -44,19 +44,19 @@ func main() { if err != nil { log.Fatalf("lookup %s: %v", flag.Args()[0], err) } - if mflag { - msg, err := apub.MarshalMail(activity) - if err != nil { - log.Println(err) + if jflag { + enc := json.NewEncoder(os.Stdout) + enc.SetIndent("", " ") + if err := enc.Encode(activity); err != nil { + os.Exit(1) } - if _, err := os.Stdout.Write(msg); err != nil { - log.Fatal(err) - } return } - enc := json.NewEncoder(os.Stdout) - enc.SetIndent("", " ") - if err := enc.Encode(activity); err != nil { - os.Exit(1) + msg, err := apub.MarshalMail(activity) + if err != nil { + log.Println(err) } + if _, err := os.Stdout.Write(msg); err != nil { + log.Fatal(err) + } } blob - 3f51c82a2505398b289ee6233753264189ca2d7c blob + a5fbda6ffee7f954b540793f4249cf258a9e5034 --- cmd/apsend/apsend.go +++ cmd/apsend/apsend.go @@ -58,7 +58,7 @@ func init() { log.SetPrefix("apsend: ") flag.BoolVar(&Fflag, "F", false, "file a copy for the sender") flag.BoolVar(&tflag, "t", false, "read recipients from message") - flag.BoolVar(&jflag, "t", false, "read ActivityPub JSON") + flag.BoolVar(&jflag, "j", false, "read ActivityPub JSON") flag.Parse() } blob - 68a66a083da7d314e9198743e60f2eaf25f93a4f blob + e7f23db6e14a2adb25d14be19a83ba273ea17d57 --- doc/apas.html +++ doc/apas.html @@ -78,13 +78,19 @@ That means understanding ActivityPub better.

a collection of small programs operate on files and streams, relaying messages out to the Internet or delivering to mailboxes on the filesystem. -But it’s so much more limited and poorly designed than upas that I was hesitant to even write this bit!

+(But it’s so much more limited and poorly designed than upas that I was hesitant to even write this bit!)

+

An important difference from existing Fediverse software is that +apas only represents Activities as messages. +There are no application-specific data structures like +posts, toots, comments, or pages. +Messages can be files in a filesystem, +which simplifies implementation significantly.

2.1 Messages

Apas marshals ActivityPub objects into RFC5322 messages and vice-versa.

The Note Activity is probably the most recognisable object exchanged by ActivityPub servers. They are represented as comments by Lemmy, and posts (toots?) by Mastodon. For instance, imagine a reply from Alex to Bowie talking about motorcycle tyres. -It’s passed around as JSON-encoded data like so:

+It’s passed around the Fediverse as JSON-encoded data like this:

{
     "type": "Note"
     "id": "https://apub.example.com/alex/12345678",
@@ -97,7 +103,7 @@ It’s passed around as JSON-encoded data like so:
 }
 

For apas this is equivalent to the mail message:

-
From: "Alice " <alice@apub.example.com>
+
From: "Alex " <alex@apub.example.com>
 To: "Bowie" <bowie@apas.test.example>
 CC: "Bowie (followers)" <bowie+followers@apas.test.example>
 Message-ID: <https://apub.example.com/alex/12345678>
@@ -106,17 +112,21 @@ Subject: Thoughts on 50/50 tyres
 
 But what if you don't know when you want to ride off-road?
 
-

Critically the mail message is written and read by people; not machines. +

Unlike other Fediverse software, +the message to be distributed is written and read by people; not just machines. For developers, administrators, and advanced users, seeing data like -this builds familiarity with the actual data exchanged and behaviour -between systems.

+this builds familiarity with the behaviour between systems, +and facilitates communication. +We go from “why can I see my toot on Kbin but not on Pleroma?” to +“why didn’t your Pleroma server receive my message?” +which is a much easier question to answer; it’s what the systems are actually doing.

If there was only one thing to take away from apas, it’s that -familiarity with data over the code is hugely helpful for -troubleshooting and understanding. Especially when typical bug reports -consist of URLs to web apps (or even just screenshots!) trying to -explain what was sent versus what was received. That’s before we we -even address what could be in a database, itself requiring its own -query language and tightly-controlled administrative access to read.

+familiarity with data over an API is hugely helpful for +troubleshooting. Especially when typical bug reports consist of URLs +to irrelevant web apps (or even just screenshots!) trying to explain +what was sent versus what was received. That’s before we we even +address what could be in a database, itself requiring its own query +language and tightly-controlled administrative access to read.

2.2. Sending

Presenting posts, comments, notes, etc. as a mail message immediately clarifies a big source of confusion with existing systems: @@ -130,20 +140,22 @@ recipients are, if any.

(or even any old text editor!) provide an interactive way to test other AP systems. For instance, we can easily test how the message is received if we address the recipient in the CC field instead of To, -or if we list the same recipient in both fields. Or 20 times over. -apas could report deliverability errors either:

+or if we list the same recipient 20 times in both fields. +Apas could report deliverability errors either:

  • immediately, or
  • as a bounced message
-

At the moment, apas returns complete error messages immediately. +

At the moment, error messages are returned immediately. This has provided a pleasant enough testing experience that makes learning ActivityPub an interactive process, -right in the mail client, especially compared with the +directly from any mail client, especially compared with the usual drudgery of sifting through logs of big web applications.

-

Sending is comprised two programs each playing its own role: -a submission program accepts messages from authorised users, -and a mailer handles sending messages to the Internet.

+

Sending is involves two programs each playing its own role:

+
    +
  1. Asubmission program accepts messages from authorised users, and
  2. +
  3. A mailer handles sending messages to the Internet.
  4. +

2.2.1. Submission

Messages are submitted to a server running apsubmit. @@ -165,7 +177,7 @@ and the built-in Mail app on my iPhone for replies. I’ll leave others to come up with more ideas; keep in mind weather stations, printers, video records can usually send email but definitely cannot speak ActivityPub!

-

In the interest of fast feedback, +

For fast feedback, apsubmit takes advantage of the RCPT stage of the SMTP transaction. It verifies that listed recipients exist and have inboxes we can target. This is in contrast with e.g. Mastodon, @@ -182,17 +194,50 @@ which will always accept creating the following post:< Mastodon never notifies of any delivery errors. We could ask the server administrators to trawl through the server’s logs for us, or ask johnny and deleteduser out-of-band if they got our message. -Accounting for these types of error at submission time obviates all that extra work.

+Accounting for some common errors at submission time obviates that extra work.

2.2.2 Mailer

Sending messages is performed by a command-line utility called apsend. apsend reads a message from standard input and disposes of it based on the recipients. -If the above message was in a file called “note.eml”, +If the above message from Alex to Bowie was in a file called “note.eml”, we could send it with the following shell command:

apsend -t < file.eml
 
-

apsend is not intended to be executed directly by users.

+

In general, apsend is not intended to be executed directly. +Instead, a frontend like an email client (sending via SMTP) +or a tool like Plan 9’s marshal(1) +should be used which take care of adding entries to and formatting the +header correctly.

2.3 Receiving

-

apserve provides a typical HTTP server for a minimal ActivityPub service. +

Core to apas is handling ActivityPub objects as files in a filesystem. +This reveals there are many different ways to retrieve Activitity from the Fediverse +beyond the typical process of servers sending Activity to an Actor’s inbox. +Apas of course supports this (see 2.3.2), +but it’s worth mentioning other techniques to show how flexible +working with the Fediverse can be. +It may also help clarify discussions on user privacy.

+

2.3.1 Direct

+

This was the first implementation of receiving ActivityPub objects for apas. +The command apget fetches the Activity at a URL, then writes it to the standard output. +Throughout testing, I ran the tool in shell scripts like the below to deliver messages to my inbox:

+
apget https://apub.example.com/alex/12345678 | apsend otl
+
+

Little shell scripts can fetch a series of posts:

+
for i in `seq 12345671 12345678`
+do
+    apget -m https://apub.example.com/alex/$i
+done
+
+

Obviously this is inefficient compared to other methods, +but we’re not Google. +Handy ad-hoc testing.

+

2.3.2 Targeting the ActivityPub inbox

+

This is the typical ActivityPub process. +For example, someone could mention us in a Mastodon post:

+
@bowie@apas.test.example hope apas is going OK!
+
+

Which results in the Mastodon server sending Activity to bowie’s Actor inbox. +In apas, +apserve provides a typical HTTP server for a minimal ActivityPub service. It is responsible for: