about summary refs log tree commit diff stats
path: root/lib/format
diff options
context:
space:
mode:
authorReto Brunner <reto@labrat.space>2019-12-18 06:34:06 +0100
committerDrew DeVault <sir@cmpwn.com>2019-12-21 09:27:53 -0500
commita744df724f8b7acb0ac231a615192d33c414012e (patch)
treeb5abf1aa47c73a39f246b9937e5774ec8e030f3a /lib/format
parent113de3596120b78aa78acb9e3335fd40029651da (diff)
downloadaerc-a744df724f8b7acb0ac231a615192d33c414012e.tar.gz
modify-labels: adapt to ProvidesMessages
Diffstat (limited to 'lib/format')
0 files changed, 0 insertions, 0 deletions
t' href='/akspecs/aerc/commit/commands/msg/unsubscribe.go?h=0.5.1&id=67fb0938a66605a0b6a837005804637b348b250d'>67fb093 ^
030f390 ^

67fb093 ^
3ba69ed ^
e2d5c45 ^
67fb093 ^


3ba69ed ^
67fb093 ^
bf28e23 ^
67fb093 ^
3ba69ed ^


030f390 ^

67fb093 ^
030f390 ^












1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118








                                      
                                         


























                                                                         




                                            











































                                                                                               
                                      

                                                    
         
                                             
                     


                                     
                   
                         
                                      
         


                          

                                                                      
                                                                 












                                                
package msg

import (
	"bufio"
	"errors"
	"net/url"
	"strings"

	"git.sr.ht/~sircmpwn/aerc/lib"
	"git.sr.ht/~sircmpwn/aerc/models"
	"git.sr.ht/~sircmpwn/aerc/widgets"
)

// Unsubscribe helps people unsubscribe from mailing lists by way of the
// List-Unsubscribe header.
type Unsubscribe struct{}

func init() {
	register(Unsubscribe{})
}

// Aliases returns a list of aliases for the :unsubscribe command
func (Unsubscribe) Aliases() []string {
	return []string{"unsubscribe"}
}

// Complete returns a list of completions
func (Unsubscribe) Complete(aerc *widgets.Aerc, args []string) []string {
	return nil
}

// Execute runs the Unsubscribe command
func (Unsubscribe) Execute(aerc *widgets.Aerc, args []string) error {
	if len(args) != 1 {
		return errors.New("Usage: unsubscribe")
	}
	widget := aerc.SelectedTab().(widgets.ProvidesMessage)
	msg, err := widget.SelectedMessage()
	if err != nil {
		return err
	}
	headers := msg.RFC822Headers
	if !headers.Has("list-unsubscribe") {
		return errors.New("No List-Unsubscribe header found")
	}
	methods := parseUnsubscribeMethods(headers.Get("list-unsubscribe"))
	aerc.Logger().Printf("found %d unsubscribe methods", len(methods))
	for _, method := range methods {
		aerc.Logger().Printf("trying to unsubscribe using %v", method)
		switch method.Scheme {
		case "mailto":
			return unsubscribeMailto(aerc, method)
		case "http", "https":
			return unsubscribeHTTP(method)
		default:
			aerc.Logger().Printf("skipping unrecognized scheme: %s", method.Scheme)
		}
	}
	return errors.New("no supported unsubscribe methods found")
}

// parseUnsubscribeMethods reads the list-unsubscribe header and parses it as a
// list of angle-bracket <> deliminated URLs. See RFC 2369.
func parseUnsubscribeMethods(header string) (methods []*url.URL) {
	r := bufio.NewReader(strings.NewReader(header))
	for {
		// discard until <
		_, err := r.ReadSlice('<')
		if err != nil {
			return
		}
		// read until <
		m, err := r.ReadSlice('>')
		if err != nil {
			return
		}
		m = m[:len(m)-1]
		if u, err := url.Parse(string(m)); err == nil {
			methods = append(methods, u)
		}
	}
}

func unsubscribeMailto(aerc *widgets.Aerc, u *url.URL) error {
	widget := aerc.SelectedTab().(widgets.ProvidesMessage)
	acct := widget.SelectedAccount()
	defaults := map[string]string{
		"To":      u.Opaque,
		"Subject": u.Query().Get("subject"),
	}
	composer, err := widgets.NewComposer(
		aerc,
		aerc.Config(),
		acct.AccountConfig(),
		acct.Worker(),
		"",
		defaults,
		models.OriginalMail{},
	)
	if err != nil {
		return err
	}
	composer.SetContents(strings.NewReader(u.Query().Get("body")))
	tab := aerc.NewTab(composer, "unsubscribe")
	composer.OnHeaderChange("Subject", func(subject string) {
		if subject == "" {
			tab.Name = "unsubscribe"
		} else {
			tab.Name = subject
		}
		tab.Content.Invalidate()
	})
	return nil
}

func unsubscribeHTTP(u *url.URL) error {
	return lib.OpenFile(u.String())
}