bool TrySubmitMailing(MailTracking tracking, string rawAuthTicketData, Recipient[] recipients, ref PartialCreateStatus partial) { Require.IsNotNull("tracking", tracking); Require.IsNotNull("recipients", recipients); Require.AtLeastOneParam("recipients", recipients); var app = tracking.Application; var env = tracking.Environment; var template = tracking.EmailTemplate; YPMon.Info("TMAIL_AGENTLOGIC_SUBMITMAILING","TrySubMailing started"); var config = StrongMailConfigurationSection.Instance; using (var easApi = config.CreateTransactionalApiWebService()) { try { var status = easApi.GetState(config.EasApiCredentials, template); YPMon.Info("TMAIL_AGENTLOGIC_SUBMITMAILING", "SendingTo StrongMail started: GetMailingId State"); if (status == ATTi.TMail.StrongMail.TransactionalApi.MailingStates.ACTIVE) { YPMon.Info("TMAIL_AGENTLOGIC_SUBMITMAILING", "SendingTo StrongMail started: GetMailingId State ACTIVE"); // Submit to StrongMail... long count = 0; var serialNo = easApi.Send(config.EasApiCredentials, template, recipients.ToStrongMailTokenStream(), out count); partial = PartialCreateStatus.Submitted; YPMon.Info("TMAIL_AGENTLOGIC_SUBMITMAILING", string.Concat("SendingTo StrongMail submitted",serialNo)); YPMon.Info("TMAIL_SAVEMAILING", string.Format("App: {0}, Env: {1}, Template: {2}, States: {3}", app, env, template, Enum.GetName(typeof(PartialCreateStatus), partial))); return ReliableRecordStatus(ref tracking, rawAuthTicketData, recipients, partial, MailTrackingStatus.Submitted, String.Concat("Mailing submitted -- StrongMail serial number: ", serialNo) ); } else if (status == ATTi.TMail.StrongMail.TransactionalApi.MailingStates.PAUSED || status == ATTi.TMail.StrongMail.TransactionalApi.MailingStates.PAUSEDOUTBOUND || status == ATTi.TMail.StrongMail.TransactionalApi.MailingStates.PAUSING || status == ATTi.TMail.StrongMail.TransactionalApi.MailingStates.PAUSINGOUTBOUND ) { partial = PartialCreateStatus.Paused; YPMon.Warn("MAILING_PAUSED", String.Concat("Mailing paused in StrongMail: ", app, "/", env, "/", template, ".")); // Schedule for a retry... the mailing is paused. Probably need a backoff strategy here! // Consider putting traffic for paused mailings into another queue, one that doesn't get // polled continually. This will reduce churn on the mq. return ReliableRecordStatus(ref tracking, rawAuthTicketData, recipients, partial, MailTrackingStatus.Paused, String.Concat("Email template paused in StrongMail: ", status) ); //return ReliableRecordStatus(ref tracking, // rawAuthTicketData, // recipients, // partial, // MailTrackingStatus.Paused, // String.Concat("Email template paused in StrongMail: ", status) // ); //return ReliableRecordStatus(ref tracking, // rawAuthTicketData, // recipients, // partial, // MailTrackingStatus.Paused, // String.Concat("Email template paused in StrongMail: ", status) // ); } else if(status ==ATTi.TMail.StrongMail.TransactionalApi.MailingStates.CANCELLED || status ==ATTi.TMail.StrongMail.TransactionalApi.MailingStates.COMPLETED || status ==ATTi.TMail.StrongMail.TransactionalApi.MailingStates.COMPLETING) { partial = PartialCreateStatus.Dropped; //TODO right now dropping paused email YPMon.Warn("MAILING_DROPPED", String.Concat("Mailing not valid in StrongMail, please check with strongmail administrator: ", app, "/", env, "/", template, ".")); return ReliableRecordStatus(ref tracking, rawAuthTicketData, recipients, partial, MailTrackingStatus.Dropped, String.Concat("Mailing not valid in StrongMail: ", status) ); } else { partial = PartialCreateStatus.Failed; YPMon.Info("TMAIL_AGENTLOGIC_SUBMITMAILING", string.Concat("SendingTo StrongMail failed", status)); YPMon.Info("TMAIL_SAVEMAILING", string.Format("App: {0}, Env: {1}, Template: {2}, States: {3}", app, env, template, Enum.GetName(typeof(PartialCreateStatus), partial))); return ReliableRecordStatus(ref tracking, rawAuthTicketData, recipients, partial, MailTrackingStatus.Failed, String.Concat("Email template not active in StrongMail: ", status) ); } } catch (WebException e) { //TODO: check what happen to strongmail webapi returns on bad mailing/bad tokens, then drop message // Probably failure to connect to SM. this.TraceData(TraceEventType.Error, e.FormatForLogging()); var capturePartial = partial; YPMon.Info("TMAIL_SAVEMAILING", string.Format("App: {0}, Env: {1}, Template: {2}, States: {3}", app, env, template, Enum.GetName(typeof(PartialCreateStatus), partial))); _output.CreateAndSendMessage<DelayedMailingMessage>(AgentProtocol.CTMailDelayed, m => { m.AuthTicket = rawAuthTicketData; m.MailTrackingID = tracking.ID; m.Application = tracking.Application; m.Environment = tracking.Environment; m.Template = tracking.EmailTemplate; m.Recipients = recipients; m.PartialStatus = capturePartial; }); return false; } catch (SoapException ex) { if (ex.Message == "Connection to TMailing daemon failed: Connection refused") { // One of the critical services in SM is down. YPMon.Critical("STRONGMAIL_UNREACHABLE", "StrongMail is unreachable.", String.Empty); this.TraceData(TraceEventType.Error, ex.FormatForLogging()); var capturePartial = partial; YPMon.Info("TMAIL_TRYSUBMITT_MAILING", string.Format("App: {0}, Env: {1}, Template: {2}, States: {3}", app, env, template, Enum.GetName(typeof(PartialCreateStatus), partial))); _output.CreateAndSendMessage<DelayedMailingMessage>(AgentProtocol.CTMailDelayed, m => { m.AuthTicket = rawAuthTicketData; m.MailTrackingID = tracking.ID; m.Application = tracking.Application; m.Environment = tracking.Environment; m.Template = tracking.EmailTemplate; m.Recipients = recipients; m.PartialStatus = capturePartial; }); return false; } if(ex.Message.Contains("Mailing is not loaded")) { partial = PartialCreateStatus.Dropped; YPMon.Warn("TMAIL_SUBMIT_BADMAILING",string.Concat("Mailing is not valid ",ex.Message)); this.TraceData(TraceEventType.Error, ex.FormatForLogging()); var capturePartial = partial; YPMon.Info("TMAIL_TRYSUBMITT_MAILING", string.Format("App: {0}, Env: {1}, Template: {2}, States: {3}", app, env, template, Enum.GetName(typeof(PartialCreateStatus), partial))); return false; } // SM doesn't give us good errors, this one can be one of dozens // that are only distinguishable by the exception text. partial = PartialCreateStatus.Failed; YPMon.Warn("STRONGMAIL_ERROR", ex.Message); return ReliableRecordStatus(ref tracking, rawAuthTicketData, recipients, partial, MailTrackingStatus.Failed, String.Concat("Failure submitting to StrongMail:", ex.Message) ); } catch (InvariantContractException e) { partial = PartialCreateStatus.Failed; YPMon.Warn("STRONGMAIL_ERROR", e.Message); YPMon.Info("TMAIL_TRYSUBMITT_MAILING", string.Format("App: {0}, Env: {1}, Template: {2}, States: {3}", app, env, template, Enum.GetName(typeof(PartialCreateStatus), partial))); return ReliableRecordStatus(ref tracking, rawAuthTicketData, recipients, partial, MailTrackingStatus.Failed, String.Concat("Bad data submitting to StrongMail:", e.Message) ); } catch (Exception ex) { var err = String.Concat("Unexpected error while submitting a mailing: ", app, "/", env, "/", template); YPMon.Critical("AGENT_UNEXPECTED_FAILURE", err, ex.FormatForLogging()); YPMon.Info("TMAIL_TRYSUBMITT_MAILING", string.Format("App: {0}, Env: {1}, Template: {2}, States: {3}", app, env, template, Enum.GetName(typeof(PartialCreateStatus), partial))); this.TraceData(TraceEventType.Error, err, ex.FormatForLogging()); throw; } } }
bool TrySaveMailing(ref MailTracking tracking, string rawAuthTicketData, ref PartialCreateStatus partial, Recipient[] recipients) { YPMon.Info("TMAIL_AGENTLOGIC_SUBMITMAILING", "TrySaveMailing started"); try { YPMon.Info("TMAIL_AGENTLOGIC_SUBMITMAILING", "TrySaveMailing Tracking started"); tracking = ExecuteDbActionsWithinTransaction(tracking, (cn, t, l) => { return PerformMailTrackingInsert(cn, t, String.Concat("Created by auth-ticket: ", rawAuthTicketData/*.GetRawAuthTicketData(false)*/)); //TODO: Signature? }); partial = PartialCreateStatus.Saved; YPMon.Info("TMAIL_AGENTLOGIC_SUBMITMAILING", "TrySaveMailing Tracking Created"); return true; } catch (ResourceAlreadyExistsException) { /* fall through, the inserting process is behind the times */ } catch (SqlException e) { if (e.Message.Contains("A network-related or instance-specific error occurred while establishing a connection to SQL Server")) { var capture = tracking; // failure during initial create... string server = (string.IsNullOrEmpty(e.Server)) ? string.Empty : e.Server; YPMon.Warn("TMAIL_SAVEMAILING_INSERTRACKING_SQLERROR", string.Format("App: {0}, Env: {1}, Template: {2}, States: {3} SQLERROR: {4} SQLServer: {5}", capture.Application, capture.Environment, capture.EmailTemplate, Enum.GetName(typeof(PartialCreateStatus), partial), e.Message,server)); _output.CreateAndSendMessage<DelayedMailingMessage>(AgentProtocol.CTMailDelayed, m => { m.AuthTicket = rawAuthTicketData; m.MailTrackingID = capture.ID; m.Application = capture.Application; m.Environment = capture.Environment; m.Template = capture.EmailTemplate; m.Recipients = recipients; m.PartialStatus = PartialCreateStatus.None; }); YPMon.Info("TMAIL_SAVEMAILING", string.Format("App: {0}, Env: {1}, Template: {2}, States: {3}", capture.Application, capture.Environment, capture.EmailTemplate, Enum.GetName(typeof(PartialCreateStatus), PartialCreateStatus.None))); } } return false; }
bool ReliableRecordStatus(ref MailTracking tracking, string rawAuthTicketData, Recipient[] recipients, PartialCreateStatus partial, MailTrackingStatus unrecordedStatus, string unrecordedNote,bool reSubmit ) { try { tracking.Status = unrecordedStatus; tracking = ExecuteDbActionsWithinTransaction(tracking, (cn, t, l) => { return PerformMailTrackingUpdate(cn, t, unrecordedNote); }); return true; } catch (SqlException e) { if (e.Message.Contains("A network-related or instance-specific error occurred while establishing a connection to SQL Server")) { YPMon.Critical("SQLSERVER_UNREACHABLE", e.FormatForLogging(), null); var capture = tracking; string server = (string.IsNullOrEmpty(e.Server)) ? string.Empty : e.Server; YPMon.Info("TMAIL_RELIABLERECORDSTATUS_INSERTRACKING_SQLERROR", string.Format("App: {0}, Env: {1}, Template: {2}, States: {3} SQLERROR: {4} SQLServer: {5}", capture.Application, capture.Environment, capture.EmailTemplate, Enum.GetName(typeof(PartialCreateStatus), partial), e.Message,server)); if (partial == PartialCreateStatus.Paused) { //_output.CreateAndSendMessage<PausedMailingMessage>(AgentProtocol.CTMailPaused, m => //{ // m.AuthTicket = rawAuthTicketData; // m.MailTrackingID = capture.ID; // m.Application = capture.Application; // m.Environment = capture.Environment; // m.Template = capture.EmailTemplate; // m.Recipients = recipients; // m.PartialStatus = partial; // m.UnrecordedStatus = unrecordedStatus; // m.UnrecordedNote = unrecordedNote; //}); } if (partial != PartialCreateStatus.Dropped) { _output.CreateAndSendMessage<DelayedMailingMessage>(AgentProtocol.CTMailDelayed, m => { m.AuthTicket = rawAuthTicketData; m.MailTrackingID = capture.ID; m.Application = capture.Application; m.Environment = capture.Environment; m.Template = capture.EmailTemplate; m.Recipients = recipients; m.PartialStatus = partial; m.UnrecordedStatus = unrecordedStatus; m.UnrecordedNote = unrecordedNote; }); } YPMon.Info("TMAIL_RECORDMAILING_STATUS", string.Format("SQLSERVER_UNREACHABLE App: {0}, Env: {1}, Template: {2}, States: {3}", capture.Application, capture.Environment, capture.EmailTemplate, Enum.GetName(typeof(PartialCreateStatus), partial))); } return false; } }
bool TryLoadTracking(Guid id, out MailTracking tracking) { try { YPMon.Info("TMAIL_AGENTLOGIC_TRYLOADTRACKING", "TryLoadTracking started"); tracking = ExecuteDbActionsWithinTransaction<MailTracking>(null, new DbAction<MailTracking>[] { (cn, a, l) => { return PerformMailTrackingSelectByID(cn, id); } }); return true; } catch (DbException e) { YPMon.Warn("TMAIL_LOADMAILINGTRACKING_SQLERROR", string.Format("Guid: {0} SQLERROR: {1} ", id.ToString(), e.Message)); } tracking = default(MailTracking); return false; }
bool ReliableRecordStatus(ref MailTracking tracking, string rawAuthTicketData, Recipient[] recipients, PartialCreateStatus partial, MailTrackingStatus unrecordedStatus, string unrecordedNote ) { return ReliableRecordStatus(ref tracking, rawAuthTicketData, recipients, partial, unrecordedStatus, unrecordedNote, true); }