Minor changes to improve testability of helpers
[castle.git] / MonoRail / Castle.MonoRail.Framework / Services / EmailTemplateService.cs
blob71bc34d9f4e7e1f29c5e44a54c4da8cf8a59b4cc
1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.MonoRail.Framework
17 using System;
18 using System.Collections;
19 using System.IO;
20 using System.Text.RegularExpressions;
21 using System.Web;
23 using Castle.Components.Common.EmailSender;
24 using Castle.Core;
25 using Castle.Core.Logging;
27 /// <summary>
28 /// Default implementation of <see cref="IEmailTemplateService"/>
29 /// </summary>
30 /// <remarks>
31 /// Will work only during a MonoRail process as it needs a <see cref="IRailsEngineContext"/>
32 /// and a <see cref="Controller"/> instance to execute.
33 /// </remarks>
34 public class EmailTemplateService : IServiceEnabledComponent, IEmailTemplateService
36 /// <summary>
37 /// The logger instance
38 /// </summary>
39 private ILogger logger = NullLogger.Instance;
41 /// <summary>
42 /// Initializes a new instance of the <see cref="EmailTemplateService"/> class.
43 /// </summary>
44 public EmailTemplateService()
48 #region IServiceEnabledComponent implementation
50 /// <summary>
51 /// Invoked by the framework in order to give a chance to
52 /// obtain other services
53 /// </summary>
54 /// <param name="provider">The service proviver</param>
55 public void Service(IServiceProvider provider)
57 ILoggerFactory loggerFactory = (ILoggerFactory) provider.GetService(typeof(ILoggerFactory));
59 if (loggerFactory != null)
61 logger = loggerFactory.Create(typeof(EmailTemplateService));
65 #endregion
67 /// <summary>
68 /// Creates an instance of <see cref="Message"/>
69 /// using the specified template for the body
70 /// </summary>
71 /// <param name="templateName">
72 /// Name of the template to load.
73 /// Will look in <c>Views/mail</c> for that template file.
74 /// </param>
75 /// <param name="parameters">
76 /// Dictionary with parameters
77 /// that you can use on the email template
78 /// </param>
79 /// <param name="doNotApplyLayout">If <c>true</c>, it will skip the layout</param>
80 /// <returns>An instance of <see cref="Message"/></returns>
81 public Message RenderMailMessage(String templateName, IDictionary parameters, bool doNotApplyLayout)
83 if (HttpContext.Current == null)
85 throw new RailsException("No http context available");
88 if (logger.IsDebugEnabled)
90 logger.DebugFormat("Rendering email message. Template name {0}", templateName);
93 IRailsEngineContext context = EngineContextModule.ObtainRailsEngineContext(HttpContext.Current);
95 IController controller = context.CurrentController;
97 if (controller == null)
99 throw new RailsException("No controller found on the executing activity");
102 if (parameters != null && parameters.Count != 0)
104 foreach(DictionaryEntry entry in parameters)
106 controller.PropertyBag.Add(entry.Key, entry.Value);
112 return RenderMailMessage(templateName, context, controller, doNotApplyLayout);
114 finally
116 if (parameters != null && parameters.Count != 0)
118 foreach(DictionaryEntry entry in parameters)
120 controller.PropertyBag.Remove(entry.Key);
126 /// <summary>
127 /// Creates an instance of <see cref="Message"/>
128 /// using the specified template for the body
129 /// </summary>
130 /// <param name="templateName">
131 /// Name of the template to load.
132 /// Will look in Views/mail for that template file.
133 /// </param>
134 /// <param name="context">Context that represents the current request</param>
135 /// <param name="controller">Controller instance</param>
136 /// <param name="doNotApplyLayout">If <c>true</c>, it will skip the layout</param>
137 /// <returns>An instance of <see cref="Message"/></returns>
138 public Message RenderMailMessage(String templateName, IRailsEngineContext context,
139 IController controller, bool doNotApplyLayout)
141 // create a message object
142 Message message = new Message();
144 // use the template engine to generate the body of the message
145 StringWriter writer = new StringWriter();
147 String oldLayout = controller.LayoutName;
149 if (doNotApplyLayout)
151 controller.LayoutName = null;
154 if (templateName.StartsWith("/"))
156 controller.InPlaceRenderSharedView(writer, templateName);
158 else
160 controller.InPlaceRenderSharedView(writer, Path.Combine(Constants.EmailTemplatePath, templateName));
163 if (doNotApplyLayout)
165 controller.LayoutName = oldLayout;
168 String body = writer.ToString();
170 // process delivery addresses from template.
171 MatchCollection matches = Constants.readdress.Matches(body);
173 for(int i = 0; i < matches.Count; i++)
175 String header = matches[i].Groups[Constants.HeaderKey].ToString().ToLower();
176 String address = matches[i].Groups[Constants.ValueKey].ToString();
178 switch(header)
180 case Constants.To :
181 message.To = address;
182 break;
183 case Constants.Cc :
184 message.Cc = address;
185 break;
186 case Constants.Bcc :
187 message.Bcc = address;
188 break;
192 if (logger.IsDebugEnabled)
194 logger.DebugFormat("Rendering email message to {0} cc {1} bcc {2}", message.To, message.Cc, message.Bcc);
197 body = Constants.readdress.Replace(body, String.Empty);
199 // process from address from template
200 Match match = Constants.refrom.Match(body);
202 if (match.Success)
204 message.From = match.Groups[Constants.ValueKey].ToString();
205 body = Constants.refrom.Replace(body, String.Empty);
208 // process subject and X headers from template
209 matches = Constants.reheader.Matches(body);
211 for(int i=0; i< matches.Count; i++)
213 String header = matches[i].Groups[Constants.HeaderKey].ToString();
214 String strval = matches[i].Groups[Constants.ValueKey].ToString();
216 if (header.ToLower(System.Globalization.CultureInfo.InvariantCulture) == Constants.Subject)
218 message.Subject = strval;
220 else
222 message.Headers.Add(header, strval);
225 if (logger.IsDebugEnabled)
227 logger.DebugFormat("Adding header {0} value {1}", header, strval);
231 body = Constants.reheader.Replace(body, String.Empty);
233 message.Body = body;
235 if (logger.IsDebugEnabled)
237 logger.DebugFormat("Email message body {0}", body);
240 // a little magic to see if the body is html
241 if (message.Body.ToLower(System.Globalization.CultureInfo.InvariantCulture).IndexOf(Constants.HtmlTag) != -1)
243 message.Format = Format.Html;
245 if (logger.IsDebugEnabled)
247 logger.Debug("Content set to Html");
251 return message;