func GetProductionMTAContainer() (mtacontainer.MTAContainer, mtacontainer.Scheduler) {
	var passphrase = GetPassphraseFromArgOrTerminal()
	var mailGunConfig = mailgunprovider.BitLabConfig(passphrase)
	var amazonConfig = amazonsesprovider.BitLabConfig(passphrase)
	var sendgridConfig = sendgridprovider.BitLabConfig(passphrase)
	providers := make([]mtacontainer.MTAProvider, 3)
	providers[0] = mailgunprovider.New(utilities.GetLogger("MailGun"), mailGunConfig, mtacontainer.NewThressHoldFailureStrategy(ERROR_THRESHOLD))
	providers[1] = amazonsesprovider.New(utilities.GetLogger("amazonSES"), amazonConfig, mtacontainer.NewThressHoldFailureStrategy(ERROR_THRESHOLD))
	providers[2] = sendgridprovider.New(utilities.GetLogger("SendGrid"), sendgridConfig, mtacontainer.NewThressHoldFailureStrategy(ERROR_THRESHOLD))
	var scheduler mtacontainer.Scheduler = mtacontainer.NewRoundRobinScheduler(providers)
	return mtacontainer.New(scheduler), scheduler
}
//
// An MTA Provider is expected to report EK_FATAL
// right before it shuts down.
//
//  Unit under test: Any MTAProvider
//
//
func Test_check_fatal_event_on_shutdown(t *testing.T) {
	c := make(chan int)
	events := make([]mtacontainer.Event, 0)
	provider := loopbackprovider.New(utilities.GetLogger("Loop"), NewMockFailureStrategy())

	go func() {
		for {
			select {
			case e := <-provider.GetEvent():
				events = append(events, e)
			case <-c:
				return
			}
		}
	}()

	provider.Stop()

	if len(events) == 0 {
		t.Error("Expected at least one event EK_FATAL event...")
	}
	c <- 0

	foundFatal := false
	for i := range events {
		if events[i].GetKind() == mtacontainer.EK_FATAL {
			foundFatal = true
		}
	}

	if foundFatal == false {
		t.Error("Expected one fatal event")
	}
}
// ------------------------------------------
//
//
// End 2 End test of the MTAContainer with Failure strategy
// and RoundRobinSchedule.
//
//
func TestEnd2End(t *testing.T) {

	//	mg := mailgunprovider.New(utilities.GetLogger("MG"),mailgunprovider.BitLabConfig("09fe27"),NewMockFailureStrategy());
	//	az := amazonsesprovider.New(utilities.GetLogger("MG"),amazonsesprovider.BitLabConfig("09fe27"),NewMockFailureStrategy());
	//  sg := sendgridprovider.New(utilities.GetLogger("MG"),sendgridprovider.BitLabConfig("09fe27"),NewMockFailureStrategy());
	var provider = loopbackprovider.New(utilities.GetLogger("loop1"), mtacontainer.NewThressHoldFailureStrategy(12))

	scheduler := mtacontainer.NewRoundRobinScheduler([]mtacontainer.MTAProvider{provider})

	container := mtacontainer.New(scheduler)

	mail1 := FreshTestMail(provider, "*****@*****.**")
	mail2 := FreshTestMail(provider, "*****@*****.**")
	mail3 := FreshTestMail(provider, "*****@*****.**")

	container.GetOutgoing() <- mail1
	container.GetOutgoing() <- mail2
	container.GetOutgoing() <- mail3

	go func() {
		<-container.GetIncoming()
	}()

	i := 0
	for {
		select {
		case e := <-container.GetEvent():
			log.Println("Reading event from container: " + e.GetError().Error())
			if i == 2 {
				return
			}
			i = i + 1
		}
	}
}
Exemple #4
0
func NewReceiveBackend(store JSonStore) *ReceiveBackEnd {
	var res *ReceiveBackEnd = new(ReceiveBackEnd)
	res.store = store
	res.incoming = make(chan model.Email)
	res.events = make(chan mtacontainer.Event)
	res.cmd = make(chan int)
	res.log = utilities.GetLogger("[Backend Server]", os.Stdout)
	go res.ListenForClientApi()

	return res
}
func main() {

	if len(os.Args) < 3 {
		println("manual_test <to address> <key>")
		return
	}

	to := os.Args[1]
	key := os.Args[2]

	mailgunMTAProvider := mailgunprovider.New(utilities.GetLogger("MailGun"),
		mailgunprovider.BitLabConfig(key), test.NewMockFailureStrategy())
	test.ManuallyVerifyEmailSend(mailgunMTAProvider, to)
}
func main() {
	if len(os.Args) < 3 {
		println("manual_test <to address> <key>")
		return
	}

	to := os.Args[1]
	key := os.Args[2]

	config := sendgridprovider.BitLabConfig(key)
	sendgridMTAProvider := sendgridprovider.New(utilities.GetLogger("SendGrid"),
		config, test.NewMockFailureStrategy())
	test.ManuallyVerifyEmailSend(sendgridMTAProvider, to)
}
func Test_one_failover(t *testing.T) {

	loop1 := loopbackprovider.New(utilities.GetLogger("loop1"), new(FailImmediatelyFailureStrategy))
	loop2 := loopbackprovider.New(utilities.GetLogger("loop2"), NewMockFailureStrategy())

	scheduler := mtacontainer.NewRoundRobinScheduler([]mtacontainer.MTAProvider{loop1, loop2})

	container := mtacontainer.New(scheduler)

	mail := FreshTestMail(loop1, "*****@*****.**")

	go func() {
		container.GetOutgoing() <- mail
		for {
			select {
			case evt := <-container.GetEvent():
				log.Println(evt.GetError().Error())
			}
		}
	}()

	// the round robin scheduler will schedule {loop1} which fails immediately
	// we expect to see {mail} emerge on the {GetIncoming} channel of {loop2}
	// because it has been RESUBMITTET to {loop2} by the fail over mechanism in
	// the MTAContainer.

	mailPrime, ok := <-loop2.GetIncoming()

	if ok == false {
		t.Error("loop2 incoming failed to provide emai.")
	}

	if mailPrime != mail {
		t.Error("Wrong mail")
	}
}
Exemple #8
0
// --------------------------------------------------------
//
// Creates a Server for the website ClientApi
//
//
//
// --------------------------------------------------------
func New(docRoot string, port int) *ClientAPI {
	var result = new(ClientAPI)
	result.docRoot = docRoot
	result.events = make(chan mtacontainer.Event)
	result.port = port
	result.log = utilities.GetLogger("[client api] ", os.Stdout)
	result.validSessions = make(map[string]string)
	versionStr, versionStrErr := ioutil.ReadFile(result.docRoot + "/version.txt")
	result.pendingMessages = make(map[string][]string)
	if versionStrErr != nil {
		result.versionStr = "No Version"
		result.log.Println(versionStrErr.Error())
	} else {
		result.versionStr = string(versionStr)
	}
	go result.serve()
	go result.listenMta()
	return result
}
func Test_all_failover(t *testing.T) {

	loop1 := loopbackprovider.New(utilities.GetLogger("loop1"), new(FailImmediatelyFailureStrategy))

	scheduler := mtacontainer.NewRoundRobinScheduler([]mtacontainer.MTAProvider{loop1})

	container := mtacontainer.New(scheduler)

	go func() {
		mail := FreshTestMail(loop1, "*****@*****.**")
		container.GetOutgoing() <- mail
		for {
			select {
			case evt := <-container.GetEvent():
				log.Println(evt.GetError().Error())
			}
		}
	}()

}
func TestLoopBack(t *testing.T) {

	loop1 := loopbackprovider.New(utilities.GetLogger("loop1"), mtacontainer.NewThressHoldFailureStrategy(1))

	mail := test.FreshTestMail(loop1, "test")

	c := make(chan int)

	go func() {
		for {
			select {
			case <-loop1.GetEvent():
			case <-c:
			}
		}
	}()

	loop1.GetOutgoing() <- mail

	<-loop1.GetIncoming()
}
Exemple #11
0
func main() {

	//
	// say hello
	//
	utilities.PrintGreeting(os.Stdout)

	//
	// Initialize logger for stdout for this mtaserver.
	//
	log := utilities.GetLogger("mtaserver")
	log.Print("Initial logger created, hi Log ")

	//
	// Start Container (ask for passphrase if necessary)
	//
	var container, _ = GetProductionMTAContainer()
	//var container, scheduler = GetLoopBackContainer();

	//
	// Print Events that occurs until GOOD_BYE.
	//
	for {
		e := <-container.GetEvent()
		log.Println(e.GetError())
		if e.GetKind() == mtacontainer.EK_GOOD_BYE {
			break
		}

		if e.GetKind() == mtacontainer.EK_INFORM_USER {
			postUserMessageWithClientAPI(e.GetError().Error(), e.GetPayload().(string))
		}
	}

	return
}
func GetLoopBackContainer() (mtacontainer.MTAContainer, mtacontainer.Scheduler) {
	var provider = loopbackprovider.New(utilities.GetLogger("LoopBack"), mtacontainer.NewThressHoldFailureStrategy(ERROR_THRESHOLD))
	var scheduler = mtacontainer.NewRoundRobinScheduler([]mtacontainer.MTAProvider{provider})
	return mtacontainer.New(scheduler), scheduler
}
Exemple #13
0
//
// Public constructor for creating a DefaultMTAContainer.
//
func New(scheduler Scheduler) MTAContainer {
	if scheduler == nil {
		return nil
	}

	var result = new(DefaultMTAContainer)
	result.providers = scheduler.GetProviders()
	result.incoming = make(chan model.Email)
	result.outgoing = make(chan model.Email)
	result.events = make(chan Event)
	result.log = utilities.GetLogger("MTAContainer")

	result.scheduler = scheduler

	// Aggregate all provider incoming and event channels to those of the MTAContainer
	for p := range result.providers {
		var pp MTAProvider = result.providers[p]

		// incoming
		go func() {
			for {
				var in = pp.GetIncoming()
				var email, ok = <-in // suppose an MTA some day delivers an email it happens here
				if ok == false {
					result.log.Println("Incoming was closed.")
				}
				result.incoming <- email
			}
		}()

		//
		// Manage MTAProviders
		//
		go func() {
			for {
				var evt = pp.GetEvent()
				var event, ok = <-evt
				if ok == false {
					result.log.Println("Event channel was closed. Terminating event listener.")
					return
				}
				//
				// Fail over
				//
				if event.GetKind() == EK_RESUBMIT {
					mail, ok := event.GetPayload().(model.Email)
					if ok {
						result.outgoing <- mail
					}
				}

				//
				// Remove dead service from schedule
				//
				if event.GetKind() == EK_FATAL {
					provider, ok := event.GetPayload().(MTAProvider)
					if ok {
						result.scheduler.RemoveProviderFromService(provider)
						if len(result.scheduler.GetProviders()) < 1 {
							result.log.Println("No MTA Providers left we shutdown.")
							result.Stop()
							result.events <- NewEvent(EK_GOOD_BYE, errors.New("Container shuts down"))
							return
						}
					}
				}

				result.events <- event
			}
		}()
	}

	// upon receiving an e-mail to send, schedule and dispatch
	go func() {
		for {

			var email = <-result.outgoing
			provider := result.scheduler.Schedule()
			if provider == nil {
				result.log.Println("Scheduler gave nil Provider")
				n := len(result.outgoing)
				for j := 0; j < n; j++ {
					result.events <- NewEvent(EK_INFORM_USER, errors.New("No MTAs availble email not sent: "+
						email.GetHeader(model.EML_HDR_SUBJECT)), email.GetSessionId())
				}
				return // no more MTAs
			}
			result.log.Println("Scheduling mail for sending on " + provider.GetName())
			provider.GetOutgoing() <- email
		}
	}()

	go result.forwardIncomingMailToBackend()
	go result.listenForSendBackEnd()

	return result
}