-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add some(what) working code and some documentation
Initial commit. Successfully pulls a message from an inbox that actually contains a message. Not perfect; there's some duplication which could be simplified, and there's the issue of panics when there are no messages available. But it's late, and I'm off to sleep now. Good night.
- Loading branch information
0 parents
commit bffef80
Showing
2 changed files
with
202 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
# go-mailin8 | ||
|
||
Display the latest mail from a temporary Mailinator email address, at | ||
the command line. | ||
|
||
Useful for getting confirmation emails for throwaway purposes, or for | ||
testing. | ||
|
||
This is a version of a [bash script I | ||
made](https://gist.github.com/StevenMaude/914e9187c09027866fe88958798acb7e) | ||
that uses [jq](https://stedolan.github.io/jq/). However, this Go version | ||
requires no other dependencies. | ||
|
||
## Build | ||
|
||
`go build` | ||
|
||
## Usage | ||
|
||
1. Send, or get an email sent to a Mailinator email address of your | ||
choosing. | ||
2. Note the local-part (the part before @, e.g. | ||
`[email protected]`). | ||
3. Run `go-mailin8 <local-part of email address>` | ||
|
||
## Notes | ||
|
||
NB: you may get unpredictable results from the server if you run this | ||
too often in a short time. See TODO. | ||
|
||
## TODO: | ||
|
||
* Fix panics on no messages. | ||
* Consider introducing slight pauses between requests to try and | ||
improve reliability. | ||
* Possibly consider selecting other than latest message (though outside | ||
of my original use case). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"os" | ||
) | ||
|
||
/* Full mail struct for posterity; generated from https://mholt.github.io/json-to-go/ | ||
type AutoGenerated struct { | ||
Data struct { | ||
Fromfull string `json:"fromfull"` | ||
Headers struct { | ||
MimeVersion string `json:"mime-version"` | ||
Date string `json:"date"` | ||
Subject string `json:"subject"` | ||
XSgEid string `json:"x-sg-eid"` | ||
MessageID string `json:"message-id"` | ||
Received string `json:"received"` | ||
From string `json:"from"` | ||
ContentType string `json:"content-type"` | ||
To string `json:"to"` | ||
DkimSignature string `json:"dkim-signature"` | ||
} `json:"headers"` | ||
Subject string `json:"subject"` | ||
RequestID string `json:"requestId"` | ||
Parts []struct { | ||
Headers struct { | ||
ContentTransferEncoding string `json:"content-transfer-encoding"` | ||
ContentType string `json:"content-type"` | ||
} `json:"headers"` | ||
Body string `json:"body"` | ||
} `json:"parts"` | ||
From string `json:"from"` | ||
Origfrom string `json:"origfrom"` | ||
To string `json:"to"` | ||
ID string `json:"id"` | ||
Time int64 `json:"time"` | ||
SecondsAgo int `json:"seconds_ago"` | ||
} `json:"data"` | ||
} */ | ||
|
||
type mail struct { | ||
Data struct { | ||
Subject string `json:"subject"` | ||
Parts []struct { | ||
Body string `json:"body"` | ||
} `json:"parts"` | ||
From string `json:"from"` | ||
} `json:"data"` | ||
} | ||
|
||
// TODO: consider dropping most of this. Can get from the message itself. | ||
type mailboxDetails struct { | ||
PublicMsgs []struct { | ||
FromFull string `json:"fromfull"` | ||
Subject string `json:"subject"` | ||
ID string `json:"id"` | ||
To string `json:"to"` | ||
} `json:"public_msgs"` | ||
} | ||
|
||
func getMailboxDetails(localPart string) (mailboxDetails, error) { | ||
webInboxURL := "https://www.mailinator.com/api/webinbox2?x=0&public_to=" + localPart | ||
fmt.Println("Retrieving URL:", webInboxURL) | ||
|
||
mbxDetails := mailboxDetails{} | ||
resp, err := http.Get(webInboxURL) | ||
if err != nil { | ||
return mbxDetails, err | ||
} | ||
|
||
defer resp.Body.Close() | ||
err = json.NewDecoder(resp.Body).Decode(&mbxDetails) | ||
if err != nil { | ||
return mbxDetails, err | ||
} | ||
return mbxDetails, err | ||
} | ||
|
||
func getCookies(mbxDetails mailboxDetails) ([]*http.Cookie, error) { | ||
// TODO: consider allow to retrieve more than one message. | ||
// TODO: fix panic on no messages. | ||
// TODO: just pass in the single message; avoid duplication? | ||
// TODO: confirm that first item is the latest message (but I think | ||
// it is from previous testing of the bash script). | ||
latestMsg := mbxDetails.PublicMsgs[0] | ||
|
||
// This request is for nothing but getting required cookies. | ||
// Otherwise, the subsequent request fails. | ||
inboxURL := "https://www.mailinator.com/inbox2.jsp?public_to=" + latestMsg.To | ||
fmt.Println("Retrieving URL:", inboxURL) | ||
|
||
inboxResp, err := http.Get(inboxURL) | ||
defer inboxResp.Body.Close() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
cookies := inboxResp.Cookies() | ||
return cookies, err | ||
} | ||
|
||
func getMail(mbxDetails mailboxDetails, cookies []*http.Cookie) error { | ||
// TODO: consider allow to retrieve more than one message. | ||
// TODO: fix panic on no messages. | ||
// TODO: just pass in the single message; avoid duplication? | ||
// TODO: confirm that first item is the latest message (but I think | ||
// it is from previous testing of the bash script). | ||
latestMsg := mbxDetails.PublicMsgs[0] | ||
|
||
msgURL := "https://www.mailinator.com/fetchmail?msgid=" + latestMsg.ID + "&zone=public" | ||
fmt.Println("Retrieving URL:", msgURL) | ||
req, err := http.NewRequest("GET", msgURL, nil) | ||
|
||
for _, c := range cookies { | ||
req.AddCookie(c) | ||
} | ||
|
||
client := &http.Client{} | ||
|
||
mailResp, err := client.Do(req) | ||
defer mailResp.Body.Close() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
mailMessage := mail{} | ||
err = json.NewDecoder(mailResp.Body).Decode(&mailMessage) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
fmt.Println("\nFrom :", mailMessage.Data.From) | ||
fmt.Println("Subject:", mailMessage.Data.Subject) | ||
fmt.Println("\n", mailMessage.Data.Parts[0].Body) | ||
return nil | ||
} | ||
|
||
func main() { | ||
if len(os.Args) != 2 { | ||
fmt.Println("Usage: mailin8 <local-part>") | ||
os.Exit(1) | ||
} | ||
|
||
localPart := os.Args[1] | ||
mbxDetails, err := getMailboxDetails(localPart) | ||
if err != nil { | ||
fmt.Println("failed to get message ID:", err) | ||
os.Exit(1) | ||
} | ||
|
||
cookies, err := getCookies(mbxDetails) | ||
if err != nil { | ||
fmt.Println("failed to get cookies:", err) | ||
os.Exit(1) | ||
} | ||
|
||
err = getMail(mbxDetails, cookies) | ||
if err != nil { | ||
fmt.Println("failed to get mail:", err) | ||
os.Exit(1) | ||
} | ||
} |