Skip to content

More refactorings #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 15 commits into from
Closed

More refactorings #2

wants to merge 15 commits into from

Conversation

dmke
Copy link
Contributor

@dmke dmke commented Apr 6, 2018

Hey,

whilst using this more, I found I needed a more conveniant interface.

The first part in this commit series will introduce a sendmail.Option type and a sendmail.New() constructor function, which takes said Options as arguments. Together, they allow code to look like this:

// taken from `sendmail_test.go`, `TestTextMail`
var buf bytes.Buffer
sm := New(
	Subject("Cześć"),
	From("Michał", "[email protected]"),
	To("Ktoś", "[email protected]"),
	To("Ktoś2", "[email protected]"),
	DebugOutput(&buf),
)

or like this:

// taken from `options_test.go`, `TestChainingOptions`
m.SetSubject("Test subject").
	SetFrom("Dominik", "[email protected]").
	AppendTo("Dominik2", "[email protected]").
	SetDebugOutput(&buf).
	SetSendmail("/bin/true")

Another subset of the commits moves the recently introduced global Binary variable, as well as the debug variable into the Mail type. As it turns out, global variables are a source of frustration in concurrent applications :-) You can see an example in the snippets above (SetOutput/SetSendmail).

I also started with HTML mails, but mixed-content (multipart, Text+HTML) isn't there yet. I'd like to harvest some code from mailyak, but the current license prevents me from that. Having a solid MIME multipart implementation would also allow attachments to the mail.

dmke added 9 commits April 6, 2018 15:10
It turns out, a global variable is not a great idea, so we move it
into the Mail object itself.

This is also introduces a new "chaninable" API: `m.SetSendmail()`
returns `m`, which allows chaining of further options (see following
commits).
Don't depend on environment variable for debug output, instead let
the consumer decide where to print to.
AppendTo might be a bit misleading, as it doesn't append the mail
to something, but appends the mail's To field. It is literally
a `To = append(To, ...)` construct.
Accepts chainable Options as arguments.
Makes testing unneccessarily hard.
Place multipart mails (HTML+Text) on the roadmap.
sendmail.go Outdated
}

// WriteTo writes headers and content of the email to io.Writer
func (m *Mail) WriteTo(wr io.Writer) error {
func (m *Mail) WriteTo(wr io.Writer) error { // nolint: vet
Copy link
Owner

@meehow meehow Apr 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are breaking compatibility with previous versions, then return values from this function can be also changed to these suggested by go vet.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was about to ask about that, but forgot.

Since writing headers doesn't return the number of bytes written, the number we'd return could either be off by that amount, or always be 0. (We could also wrap the wr with something that counts the number of bytes written for us, but honestly, I don't think it matters that much...)

What do you think?

options.go Outdated
// AppendTo adds a recipient to the Mail. The name argument is the
// "proper name" of the recipient and may be empty. The address must be
// in the form "user@domain".
func (m *Mail) AppendTo(name, address string) *Mail {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we can use *mail.Address directly, it's a build in type. I can imagine situation when somebody used ParseAddress, which returns *mail.Address, then he need to convert it to 2 strings and we convert it back to *mail.Address. That would be a bit over engineered. Using mail.Address as a function parameter doesn't bring that much complexity I think: AppendTo(&mail.Address{Name: "someone", Address: "some@email"}). @dmke what do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be OK with that.

dmke added 2 commits April 9, 2018 12:22
WriteTo now returns (int64, error); however the returned number of bytes
written is always 0, since we don't get the actual number easily.
@dmke
Copy link
Contributor Author

dmke commented Apr 9, 2018

I've addressed your comments and added some commits.

I will now try to fix the issue of m.Header.Write(wr) not returning the number of bytes.

@dmke
Copy link
Contributor Author

dmke commented Apr 9, 2018

FYI: I've worked on this on company time, so I need to move the code to my emplyers repository. This may require a new PR, depending on how Github handles moving repos :-)

@dmke
Copy link
Contributor Author

dmke commented May 25, 2018

Any chance to get this merged in?

@dmke dmke mentioned this pull request Aug 2, 2018
@dmke
Copy link
Contributor Author

dmke commented Aug 2, 2018

Im closing this in favour of #3. This PR is (unfortunately) based on our master branch. For #3 I've moved the commits into a seperate branch.

@dmke dmke closed this Aug 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants