Revision | 111 (tree) |
---|---|
Zeit | 2020-07-02 17:16:14 |
Autor | ![]() |
* メール送信でエラーの場合は重要度=緊急で送信する
* EWatch.config.json に General.name を追加
@@ -37,6 +37,7 @@ | ||
37 | 37 | { |
38 | 38 | string timestampString = (data.TimeStamp ?? DateTime.Now).ToString("yyyy-MM-dd HH:mm:ss.fff"); |
39 | 39 | string cmdLine = CommandLine |
40 | + .Replace("$name", data.Name) | |
40 | 41 | .Replace("$timestamp", timestampString) |
41 | 42 | .Replace("$hostname", data.HostName) |
42 | 43 | .Replace("$source", data.Source) |
@@ -146,6 +146,9 @@ | ||
146 | 146 | result.AppendFormat("level:\t{0}\r\n", data.Level); |
147 | 147 | result.AppendFormat("code:\t{0}\r\n", data.Code); |
148 | 148 | } |
149 | + if(!Util.IsNullOrEmpty(data.Name)){ | |
150 | + result.AppendFormat("name:\t{0}\r\n", data.Name); | |
151 | + } | |
149 | 152 | if(!Util.IsNullOrEmpty(data.HostName)){ |
150 | 153 | result.AppendFormat("host:\t{0}\r\n", data.HostName); |
151 | 154 | } |
@@ -33,11 +33,13 @@ | ||
33 | 33 | |
34 | 34 | public override void Execute(LogData data) |
35 | 35 | { |
36 | - lock(lockObject){ | |
36 | + lock (lockObject) { | |
37 | 37 | var subject = string.Format("[{0}] {1}", data.HostName, DeleteTimestamp(data.Message)); |
38 | - if(subject.Length > 255) | |
38 | + if (!string.IsNullOrEmpty(data.Name)) | |
39 | + subject = string.Format("[{0}]{1}", data.Name, subject); | |
40 | + if (subject.Length > 255) | |
39 | 41 | subject = subject.Substring(0, 255); |
40 | - if(!IsIssued(subject)){ | |
42 | + if (!IsIssued(subject)) { | |
41 | 43 | SendIssue(subject, data); |
42 | 44 | } |
43 | 45 | } |
@@ -45,19 +47,19 @@ | ||
45 | 47 | |
46 | 48 | public override bool Validate() |
47 | 49 | { |
48 | - if(Util.IsNullOrEmpty(BaseUrl)){ | |
50 | + if (Util.IsNullOrEmpty(BaseUrl)) { | |
49 | 51 | log.Error("BaseUrl is not specified."); |
50 | 52 | return false; |
51 | 53 | } |
52 | - if(Util.IsNullOrEmpty(APIKey)){ | |
54 | + if (Util.IsNullOrEmpty(APIKey)) { | |
53 | 55 | log.Error("APIKey is not specified."); |
54 | 56 | return false; |
55 | 57 | } |
56 | - if(Util.IsNullOrEmpty(ProjectID)){ | |
58 | + if (Util.IsNullOrEmpty(ProjectID)) { | |
57 | 59 | log.Error("ProjectID is not specified."); |
58 | 60 | return false; |
59 | 61 | } |
60 | - if(Util.IsNullOrEmpty(TrackerID)){ | |
62 | + if (Util.IsNullOrEmpty(TrackerID)) { | |
61 | 63 | log.Error("TrackerID is not specified."); |
62 | 64 | return false; |
63 | 65 | } |
@@ -82,10 +84,10 @@ | ||
82 | 84 | var json = Request("/issues.json?author_id=me&status_id=open&sort=created_on:desc&limit=100", null, null); |
83 | 85 | var jo = JObject.Parse(json); |
84 | 86 | var jarray = jo["issues"] as JArray; |
85 | - if(jarray != null){ | |
86 | - foreach(var issue in jarray){ | |
87 | + if (jarray != null) { | |
88 | + foreach (var issue in jarray) { | |
87 | 89 | var s = issue["subject"].ToString(); |
88 | - if(subject.Equals(s)){ | |
90 | + if (subject.Equals(s)) { | |
89 | 91 | return true; |
90 | 92 | } |
91 | 93 | } |
@@ -113,12 +115,12 @@ | ||
113 | 115 | var req = (HttpWebRequest)WebRequest.Create(url); |
114 | 116 | req.Headers.Add("X-Redmine-API-Key", APIKey); |
115 | 117 | req.Method = string.IsNullOrEmpty(postData) ? "GET" : "POST"; |
116 | - if(!string.IsNullOrEmpty(contentType)) | |
118 | + if (!string.IsNullOrEmpty(contentType)) | |
117 | 119 | req.ContentType = contentType; |
118 | 120 | req.ContentLength = data.Length; |
119 | 121 | |
120 | - if(!Util.IsNullOrEmpty(data)){ | |
121 | - using(Stream s = req.GetRequestStream()){ | |
122 | + if (!Util.IsNullOrEmpty(data)) { | |
123 | + using (Stream s = req.GetRequestStream()) { | |
122 | 124 | s.Write(data, 0, data.Length); |
123 | 125 | } |
124 | 126 | } |
@@ -125,7 +127,7 @@ | ||
125 | 127 | |
126 | 128 | string result = null; |
127 | 129 | WebResponse res = req.GetResponse(); |
128 | - using(var sr = new StreamReader(res.GetResponseStream())){ | |
130 | + using (var sr = new StreamReader(res.GetResponseStream())) { | |
129 | 131 | result = sr.ReadToEnd(); |
130 | 132 | } |
131 | 133 | return result; |
@@ -135,14 +137,17 @@ | ||
135 | 137 | { |
136 | 138 | var result = new StringBuilder(); |
137 | 139 | result.AppendFormat("Time:\t{0}\r\n", data.TimeStamp.Value.ToString("yyyy-MM-dd HH:mm:ss.fff")); |
138 | - if(!Util.IsNullOrEmpty(data.Level)){ | |
140 | + if (!Util.IsNullOrEmpty(data.Level)) { | |
139 | 141 | result.AppendFormat("level:\t{0}\r\n", data.Level); |
140 | 142 | result.AppendFormat("code:\t{0}\r\n", data.Code); |
141 | 143 | } |
142 | - if(!Util.IsNullOrEmpty(data.HostName)){ | |
144 | + if (!Util.IsNullOrEmpty(data.Name)) { | |
145 | + result.AppendFormat("name:\t{0}\r\n", data.Name); | |
146 | + } | |
147 | + if (!Util.IsNullOrEmpty(data.HostName)) { | |
143 | 148 | result.AppendFormat("host:\t{0}\r\n", data.HostName); |
144 | 149 | } |
145 | - if(!Util.IsNullOrEmpty(data.Source)){ | |
150 | + if (!Util.IsNullOrEmpty(data.Source)) { | |
146 | 151 | result.AppendFormat("source:\t{0}\r\n", data.Source); |
147 | 152 | } |
148 | 153 | result.AppendFormat("{0}\r\n", data.Message); |
@@ -57,12 +57,12 @@ | ||
57 | 57 | |
58 | 58 | public override bool Validate() |
59 | 59 | { |
60 | - if(Util.IsNullOrEmpty(URL)){ | |
60 | + if (Util.IsNullOrEmpty(URL)) { | |
61 | 61 | log.Error("Token is not specified."); |
62 | 62 | return false; |
63 | 63 | } |
64 | - if(!Util.IsNullOrEmpty(Attachments)){ | |
65 | - if(JsonUtil.Parse(Attachments) == null){ | |
64 | + if (!Util.IsNullOrEmpty(Attachments)) { | |
65 | + if (JsonUtil.Parse(Attachments) == null) { | |
66 | 66 | log.Error("Attachments is invalid."); |
67 | 67 | return false; |
68 | 68 | } |
@@ -74,30 +74,34 @@ | ||
74 | 74 | { |
75 | 75 | var text = new StringBuilder(); |
76 | 76 | text.AppendFormat("Time: {0}\n", data.TimeStamp.Value.ToString("yyyy-MM-dd HH:mm:ss.fff")); |
77 | - if(!Util.IsNullOrEmpty(data.Level)){ | |
77 | + if (!Util.IsNullOrEmpty(data.Level)) { | |
78 | 78 | text.AppendFormat("level: {0}\n", data.Level); |
79 | 79 | text.AppendFormat("code: {0}\n", data.Code); |
80 | 80 | } |
81 | - if(!Util.IsNullOrEmpty(data.HostName)){ | |
81 | + if (!Util.IsNullOrEmpty(data.Name)) { | |
82 | + text.AppendFormat("name: {0}\n", data.Name); | |
83 | + } | |
84 | + if (!Util.IsNullOrEmpty(data.HostName)) { | |
82 | 85 | text.AppendFormat("host: {0}\n", data.HostName); |
83 | 86 | } |
84 | - if(!Util.IsNullOrEmpty(data.Source)){ | |
87 | + if (!Util.IsNullOrEmpty(data.Source)) { | |
85 | 88 | text.AppendFormat("source: {0}\n", data.Source); |
86 | 89 | } |
87 | 90 | text.AppendFormat("{0}\n", data.Message); |
88 | - Send(string.Concat("payload=", HttpUtility.UrlEncode(GetJSON( | |
89 | - string.Format("[{0}] {1}", data.HostName, GetSubject(data.Message)), | |
90 | - text.ToString())))); | |
91 | + var subject = string.Format("[{0}] {1}", data.HostName, GetSubject(data.Message)); | |
92 | + if (!Util.IsNullOrEmpty(data.Name)) | |
93 | + subject = string.Format("[{0}]{1}", data.Name, subject); | |
94 | + Send(string.Concat("payload=", HttpUtility.UrlEncode(GetJSON(subject, text.ToString())))); | |
91 | 95 | } |
92 | 96 | |
93 | 97 | private string GetSubject(string value) |
94 | 98 | { |
95 | - if(!string.IsNullOrEmpty(value)){ | |
99 | + if (!string.IsNullOrEmpty(value)) { | |
96 | 100 | // 改行があればそこで区切る |
97 | 101 | var array = value.Split('\n'); |
98 | 102 | value = array[0]; |
99 | 103 | // 255文字以上ならそこで区切る |
100 | - if(value.Length > 255) | |
104 | + if (value.Length > 255) | |
101 | 105 | value = value.Substring(0, 255); |
102 | 106 | } |
103 | 107 | return value; |
@@ -106,25 +110,25 @@ | ||
106 | 110 | private string GetJSON(string title, string text) |
107 | 111 | { |
108 | 112 | var jo = new JObject(); |
109 | - if(!Util.IsNullOrEmpty(Attachments)){ | |
113 | + if (!Util.IsNullOrEmpty(Attachments)) { | |
110 | 114 | var attachment = JsonUtil.Parse(Attachments) as JObject; |
111 | 115 | attachment["title"] = title; |
112 | 116 | attachment["text"] = text; |
113 | 117 | attachment["fallback"] = title; |
114 | - jo["attachments"] = new JArray(attachment);; | |
115 | - } | |
116 | - else { | |
118 | + jo["attachments"] = new JArray(attachment); | |
119 | + ; | |
120 | + } else { | |
117 | 121 | jo["text"] = string.Join("\n", title, text); |
118 | 122 | } |
119 | - if(!Util.IsNullOrEmpty(UserName)){ | |
123 | + if (!Util.IsNullOrEmpty(UserName)) { | |
120 | 124 | jo["as_user"] = "0"; |
121 | 125 | jo["username"] = UserName; |
122 | 126 | } |
123 | - if(!Util.IsNullOrEmpty(IconEmoji)){ | |
127 | + if (!Util.IsNullOrEmpty(IconEmoji)) { | |
124 | 128 | jo["as_user"] = "0"; |
125 | 129 | jo["icon_emoji"] = IconEmoji; |
126 | 130 | } |
127 | - if(!Util.IsNullOrEmpty(Channel)){ | |
131 | + if (!Util.IsNullOrEmpty(Channel)) { | |
128 | 132 | jo["channel"] = Channel; |
129 | 133 | } |
130 | 134 | return jo.ToString(); |
@@ -138,13 +142,13 @@ | ||
138 | 142 | req.ContentType = "application/x-www-form-urlencoded"; |
139 | 143 | req.ContentLength = data.Length; |
140 | 144 | |
141 | - using(Stream s = req.GetRequestStream()){ | |
145 | + using (Stream s = req.GetRequestStream()) { | |
142 | 146 | s.Write(data, 0, data.Length); |
143 | 147 | } |
144 | 148 | |
145 | 149 | string result = null; |
146 | 150 | WebResponse res = req.GetResponse(); |
147 | - using(var sr = new StreamReader(res.GetResponseStream())){ | |
151 | + using (var sr = new StreamReader(res.GetResponseStream())) { | |
148 | 152 | result = sr.ReadToEnd(); |
149 | 153 | } |
150 | 154 | return result; |
@@ -35,7 +35,7 @@ | ||
35 | 35 | string[] hostAndPort = value.Split(new char[]{ ':' }); |
36 | 36 | _serverHost = hostAndPort[0]; |
37 | 37 | _serverPort = 25; |
38 | - if(hostAndPort.Length >= 2){ | |
38 | + if (hostAndPort.Length >= 2) { | |
39 | 39 | int.TryParse(hostAndPort[1], out _serverPort); |
40 | 40 | } |
41 | 41 | } |
@@ -55,15 +55,15 @@ | ||
55 | 55 | |
56 | 56 | public override bool Validate() |
57 | 57 | { |
58 | - if(Util.IsNullOrEmpty(_serverHost)){ | |
58 | + if (Util.IsNullOrEmpty(_serverHost)) { | |
59 | 59 | log.Error("ServerHost is not specified."); |
60 | 60 | return false; |
61 | 61 | } |
62 | - if(Util.IsNullOrEmpty(FromAddress)){ | |
62 | + if (Util.IsNullOrEmpty(FromAddress)) { | |
63 | 63 | log.Error("FromAddress is not specified."); |
64 | 64 | return false; |
65 | 65 | } |
66 | - if(Util.IsNullOrEmpty(ToAddress)){ | |
66 | + if (Util.IsNullOrEmpty(ToAddress)) { | |
67 | 67 | log.Error("ToAddress is not specified."); |
68 | 68 | return false; |
69 | 69 | } |
@@ -72,46 +72,54 @@ | ||
72 | 72 | |
73 | 73 | public override void Execute(LogData data) |
74 | 74 | { |
75 | - lock(lockObject){ | |
75 | + lock (lockObject) { | |
76 | 76 | StringBuilder body = new StringBuilder(); |
77 | 77 | body.AppendFormat("Time: {0}\r\n", data.TimeStamp.Value.ToString("yyyy-MM-dd HH:mm:ss.fff")); |
78 | - if(!Util.IsNullOrEmpty(data.Level)){ | |
78 | + if (!Util.IsNullOrEmpty(data.Level)) { | |
79 | 79 | body.AppendFormat("level: {0}\r\n", data.Level); |
80 | 80 | body.AppendFormat("code: {0}\r\n", data.Code); |
81 | 81 | } |
82 | - if(!Util.IsNullOrEmpty(data.HostName)){ | |
82 | + if (!Util.IsNullOrEmpty(data.Name)) { | |
83 | + body.AppendFormat("name: {0}\r\n", data.Name); | |
84 | + } | |
85 | + if (!Util.IsNullOrEmpty(data.HostName)) { | |
83 | 86 | body.AppendFormat("host: {0}\r\n", data.HostName); |
84 | 87 | } |
85 | - if(!Util.IsNullOrEmpty(data.Source)){ | |
88 | + if (!Util.IsNullOrEmpty(data.Source)) { | |
86 | 89 | body.AppendFormat("source: {0}\r\n", data.Source); |
87 | 90 | } |
88 | 91 | body.AppendFormat("{0}\r\n", data.Message); |
89 | - Send(GetSubject(string.Format("[{0}] {1}", data.HostName, data.Message)), body.ToString()); | |
92 | + var subject = string.Format("[{0}] {1}", data.HostName, data.Message); | |
93 | + if (!string.IsNullOrEmpty(data.Name)) | |
94 | + subject = string.Format("[{0}]{1}", data.Name, subject); | |
95 | + Send(GetSubject(subject), | |
96 | + body.ToString(), | |
97 | + data.Level == "E"); | |
90 | 98 | } |
91 | 99 | } |
92 | 100 | |
93 | 101 | private string GetSubject(string value) |
94 | 102 | { |
95 | - if(!string.IsNullOrEmpty(value)){ | |
103 | + if (!string.IsNullOrEmpty(value)) { | |
96 | 104 | // 改行があればそこで区切る |
97 | 105 | var array = value.Split('\n'); |
98 | 106 | value = array[0]; |
99 | 107 | // 76文字以上ならそこで区切る |
100 | - if(value.Length > 76) | |
108 | + if (value.Length > 76) | |
101 | 109 | value = value.Substring(0, 76); |
102 | 110 | } |
103 | 111 | return value; |
104 | 112 | } |
105 | 113 | |
106 | - private void Send(string subject, string body) | |
114 | + private void Send(string subject, string body, bool urgent) | |
107 | 115 | { |
108 | - using(var sender = new EMailSender(_serverHost, _serverPort, | |
109 | - Protection, AuthMethod, | |
110 | - UserID, Password, null)){ | |
116 | + using (var sender = new EMailSender(_serverHost, _serverPort, | |
117 | + Protection, AuthMethod, | |
118 | + UserID, Password, null)) { | |
111 | 119 | sender.Send(subject, body, |
112 | - new MailAddress(FromAddress), | |
113 | - ToAddress.Split(',').Select(x => new MailAddress(x)).ToArray(), | |
114 | - null, null); | |
120 | + new MailAddress(FromAddress), | |
121 | + ToAddress.Split(',').Select(x => new MailAddress(x)).ToArray(), | |
122 | + null, null, urgent); | |
115 | 123 | } |
116 | 124 | } |
117 | 125 | } |
@@ -71,7 +71,10 @@ | ||
71 | 71 | jo["themeColor"] = ThemeColor; |
72 | 72 | } |
73 | 73 | jo["summary"] = string.Format("notification from {0}", data.HostName); |
74 | - jo["title"] = string.Format("[{0}] {1}", data.HostName, GetSubject(data.Message)); | |
74 | + var subject = string.Format("[{0}] {1}", data.HostName, GetSubject(data.Message)); | |
75 | + if (!string.IsNullOrEmpty(data.Name)) | |
76 | + subject = string.Format("[{0}]{1}", data.Name, subject); | |
77 | + jo["title"] = subject; | |
75 | 78 | jo["sections"] = new JArray(GetSection(data)); |
76 | 79 | return jo.ToString(); |
77 | 80 | } |
@@ -83,6 +86,7 @@ | ||
83 | 86 | GetFact("Time", data.TimeStamp.Value.ToString("yyyy-MM-dd HH:mm:ss.fff")), |
84 | 87 | GetFact("Level", data.Level), |
85 | 88 | GetFact("Code", data.Code.ToString()), |
89 | + GetFact("Name", data.Name), | |
86 | 90 | GetFact("Host", data.HostName), |
87 | 91 | GetFact("Source", data.Source) |
88 | 92 | ); |
@@ -94,7 +98,7 @@ | ||
94 | 98 | { |
95 | 99 | dynamic result = new JObject(); |
96 | 100 | result.name = name; |
97 | - result.value = value; | |
101 | + result.value = value ?? string.Empty; | |
98 | 102 | return result; |
99 | 103 | } |
100 | 104 |
@@ -78,6 +78,7 @@ | ||
78 | 78 | value); |
79 | 79 | } |
80 | 80 | } |
81 | + public GeneralConfiguration General { get; private set; } | |
81 | 82 | public ServerConfiguration Server { get; private set; } |
82 | 83 | |
83 | 84 | public Configuration() : this(true) |
@@ -136,6 +137,15 @@ | ||
136 | 137 | return result; |
137 | 138 | } |
138 | 139 | |
140 | + private void GetGeneralSettings(object jobject) | |
141 | + { | |
142 | + if(jobject != null){ | |
143 | + General = new GeneralConfiguration { | |
144 | + Name = JsonUtil.GetString(jobject, "name") | |
145 | + }; | |
146 | + } | |
147 | + } | |
148 | + | |
139 | 149 | private void GetActions(object jobject) |
140 | 150 | { |
141 | 151 | if(jobject != null){ |
@@ -156,6 +166,8 @@ | ||
156 | 166 | private void ParseJson(string json) |
157 | 167 | { |
158 | 168 | object j = JsonUtil.Parse(json); |
169 | + object general = JsonUtil.GetObject(j, "General"); | |
170 | + GetGeneralSettings(general); | |
159 | 171 | object actions = JsonUtil.GetObject(j, "Actions"); |
160 | 172 | if(actions == null) |
161 | 173 | throw new InvalidDataException(); |
@@ -273,6 +285,10 @@ | ||
273 | 285 | JsonUtil.Get<ServerConfiguration>(json, Server); |
274 | 286 | } |
275 | 287 | |
288 | + public class GeneralConfiguration | |
289 | + { | |
290 | + public string Name { get; set; } | |
291 | + } | |
276 | 292 | |
277 | 293 | public class ServerConfiguration |
278 | 294 | { |
@@ -16,6 +16,7 @@ | ||
16 | 16 | /// </summary> |
17 | 17 | public class LogData |
18 | 18 | { |
19 | + public string Name { get; set; } | |
19 | 20 | public string HostName { get; set; } |
20 | 21 | public DateTime? TimeStamp { get; set; } |
21 | 22 | public string Source { get; set; } |
@@ -1,27 +1,23 @@ | ||
1 | -#region Using directives | |
2 | - | |
1 | +#region Using directives | |
3 | 2 | using System; |
4 | 3 | using System.Reflection; |
5 | 4 | using System.Runtime.InteropServices; |
6 | 5 | |
7 | 6 | #endregion |
8 | - | |
9 | 7 | // General Information about an assembly is controlled through the following |
10 | 8 | // set of attributes. Change these attribute values to modify the information |
11 | 9 | // associated with an assembly. |
12 | -[assembly: AssemblyTitle("EWatch")] | |
13 | -[assembly: AssemblyDescription("")] | |
14 | -[assembly: AssemblyConfiguration("")] | |
15 | -[assembly: AssemblyCompany("")] | |
16 | -[assembly: AssemblyProduct("EWatch")] | |
17 | -[assembly: AssemblyCopyright("Copyright 2013-2018 BananaJinn")] | |
18 | -[assembly: AssemblyTrademark("")] | |
19 | -[assembly: AssemblyCulture("")] | |
20 | - | |
10 | +[assembly: AssemblyTitle ("EWatch")] | |
11 | +[assembly: AssemblyDescription ("")] | |
12 | +[assembly: AssemblyConfiguration ("")] | |
13 | +[assembly: AssemblyCompany ("")] | |
14 | +[assembly: AssemblyProduct ("EWatch")] | |
15 | +[assembly: AssemblyCopyright ("Copyright 2013-2018 BananaJinn")] | |
16 | +[assembly: AssemblyTrademark ("")] | |
17 | +[assembly: AssemblyCulture ("")] | |
21 | 18 | // This sets the default COM visibility of types in the assembly to invisible. |
22 | 19 | // If you need to expose a type to COM, use [ComVisible(true)] on that type. |
23 | -[assembly: ComVisible(false)] | |
24 | - | |
20 | +[assembly: ComVisible (false)] | |
25 | 21 | // The assembly version has following format : |
26 | 22 | // |
27 | 23 | // Major.Minor.Build.Revision |
@@ -28,6 +24,5 @@ | ||
28 | 24 | // |
29 | 25 | // You can specify all the values or you can use the default the Revision and |
30 | 26 | // Build Numbers by using the '*' as shown below: |
31 | -[assembly: AssemblyVersion("1.0.30")] | |
32 | - | |
33 | -//[assembly: log4net.Config.XmlConfigurator(ConfigFile=@"Log4net.Config.xml", Watch=true)] | |
\ No newline at end of file | ||
27 | +[assembly: AssemblyVersion ("1.0.30")] | |
28 | +//[assembly: log4net.Config.XmlConfigurator(ConfigFile=@"Log4net.Config.xml", Watch=true)] |
@@ -42,7 +42,7 @@ | ||
42 | 42 | } |
43 | 43 | |
44 | 44 | public EMailSender(string server, int port, Protections protection, AuthenticateMethods authMethod, |
45 | - string userId, string password, string userAgent) | |
45 | + string userId, string password, string userAgent) | |
46 | 46 | { |
47 | 47 | Server = server; |
48 | 48 | Port = port; |
@@ -54,10 +54,11 @@ | ||
54 | 54 | } |
55 | 55 | |
56 | 56 | public void Send(string subject, string body, |
57 | - MailAddress fromAddress, | |
58 | - MailAddress[] toAddresses, | |
59 | - MailAddress[] ccAddresses, | |
60 | - MailAddress[] bccAddresses) | |
57 | + MailAddress fromAddress, | |
58 | + MailAddress[] toAddresses, | |
59 | + MailAddress[] ccAddresses, | |
60 | + MailAddress[] bccAddresses, | |
61 | + bool urgent) | |
61 | 62 | { |
62 | 63 | Connect(); |
63 | 64 | SendMailFrom(fromAddress.Address); |
@@ -65,23 +66,27 @@ | ||
65 | 66 | var headers = new List<string>(); |
66 | 67 | |
67 | 68 | headers.AddRange(CreateHeader("From", fromAddress)); |
68 | - if(toAddresses != null){ | |
69 | + if (toAddresses != null) { | |
69 | 70 | addresses.AddRange(toAddresses.Select(x => x.Address)); |
70 | 71 | headers.AddRange(CreateHeader("To", toAddresses)); |
71 | 72 | } |
72 | - if(ccAddresses != null){ | |
73 | + if (ccAddresses != null) { | |
73 | 74 | addresses.AddRange(ccAddresses.Select(x => x.Address)); |
74 | 75 | headers.AddRange(CreateHeader("Cc", ccAddresses)); |
75 | 76 | } |
76 | - if(bccAddresses != null){ | |
77 | + if (bccAddresses != null) { | |
77 | 78 | addresses.AddRange(bccAddresses.Select(x => x.Address)); |
78 | 79 | } |
79 | - if(subject != null){ | |
80 | + if (subject != null) { | |
80 | 81 | headers.AddRange(CreateHeader("Subject", subject)); |
81 | 82 | } |
82 | 83 | headers.AddRange(CreateHeader("Content-Type", "text/plain; charset=utf-8; format=flowed")); |
83 | 84 | headers.AddRange(CreateHeader("Content-Transfer-Encoding", "8bit")); |
84 | 85 | headers.AddRange(CreateHeader("User-Agent", UserAgent)); |
86 | + if (urgent) { | |
87 | + headers.AddRange(CreateHeader("Priority", "urgent")); | |
88 | + headers.AddRange(CreateHeader("X-Priority", "1")); | |
89 | + } | |
85 | 90 | headers.Add(string.Empty); |
86 | 91 | headers.Add(string.Empty); |
87 | 92 | SendRcptTo(addresses.ToArray()); |
@@ -93,19 +98,19 @@ | ||
93 | 98 | |
94 | 99 | private void Connect() |
95 | 100 | { |
96 | - if(!string.IsNullOrEmpty(DumpFile)){ | |
101 | + if (!string.IsNullOrEmpty(DumpFile)) { | |
97 | 102 | OpenDumpFile(DumpFile); |
98 | 103 | return; |
99 | 104 | } |
100 | - if(!Connected){ | |
105 | + if (!Connected) { | |
101 | 106 | Connect(Server, Port, Protection == Protections.SslTls); |
102 | 107 | Receive(); |
103 | 108 | SendEHlo(); |
104 | - if(Protection == Protections.StartTls){ | |
109 | + if (Protection == Protections.StartTls) { | |
105 | 110 | SendStartTls(); |
106 | 111 | SendEHlo(); |
107 | 112 | } |
108 | - switch(AuthenticateMethod){ | |
113 | + switch (AuthenticateMethod) { | |
109 | 114 | case AuthenticateMethods.Plain: |
110 | 115 | SendAuthPlain(UserID, UserID, Password); |
111 | 116 | break; |
@@ -126,17 +131,16 @@ | ||
126 | 131 | { |
127 | 132 | var sb = new EMailStringBuilder(); |
128 | 133 | sb.Append(name).Append(": "); |
129 | - var lastIndex = addresses.Length-1; | |
130 | - for(int index=0; index<addresses.Length; index++){ | |
134 | + var lastIndex = addresses.Length - 1; | |
135 | + for (int index = 0; index < addresses.Length; index++) { | |
131 | 136 | var address = addresses[index]; |
132 | - if(!string.IsNullOrEmpty(address.DisplayName)){ | |
137 | + if (!string.IsNullOrEmpty(address.DisplayName)) { | |
133 | 138 | sb.Append(address.DisplayName); |
134 | 139 | sb.Append(string.Concat(string.Format(" <{0}>", address.Address), |
135 | - lastIndex == index ? string.Empty : ",")); | |
136 | - } | |
137 | - else{ | |
140 | + lastIndex == index ? string.Empty : ",")); | |
141 | + } else { | |
138 | 142 | sb.Append(string.Concat(address.Address, |
139 | - lastIndex == index ? string.Empty : ",")); | |
143 | + lastIndex == index ? string.Empty : ",")); | |
140 | 144 | } |
141 | 145 | } |
142 | 146 | return sb.ToStrings(); |
@@ -145,7 +149,8 @@ | ||
145 | 149 | /// <summary> |
146 | 150 | /// 接続保護モード |
147 | 151 | /// </summary> |
148 | - public enum Protections { | |
152 | + public enum Protections | |
153 | + { | |
149 | 154 | None, |
150 | 155 | StartTls, |
151 | 156 | SslTls, |
@@ -154,7 +159,8 @@ | ||
154 | 159 | /// <summary> |
155 | 160 | /// 認証モード |
156 | 161 | /// </summary> |
157 | - public enum AuthenticateMethods { | |
162 | + public enum AuthenticateMethods | |
163 | + { | |
158 | 164 | None, |
159 | 165 | Plain, |
160 | 166 | Login, |
@@ -20,14 +20,16 @@ | ||
20 | 20 | /// </summary> |
21 | 21 | public class EventLogWatcher : BaseWatcher |
22 | 22 | { |
23 | + private Configuration.GeneralConfiguration generalConf; | |
23 | 24 | private string name; |
24 | -#if _WINDOWS | |
25 | + #if _WINDOWS | |
25 | 26 | private EventBookmark bookmark; |
26 | 27 | #endif |
27 | 28 | |
28 | - public EventLogWatcher(string name, List<ActionTable> actionTable) | |
29 | + public EventLogWatcher(Configuration.GeneralConfiguration generalConf, string name, List<ActionTable> actionTable) | |
29 | 30 | : base(actionTable) |
30 | 31 | { |
32 | + this.generalConf = generalConf; | |
31 | 33 | this.name = name; |
32 | 34 | } |
33 | 35 |
@@ -94,6 +96,7 @@ | ||
94 | 96 | } |
95 | 97 | if (rec.TimeCreated > DateTime.Now.AddDays(-1)) { |
96 | 98 | FindAndExecute(new LogData { |
99 | + Name = generalConf != null ? generalConf.Name : null, | |
97 | 100 | Code = rec.Id, |
98 | 101 | HostName = rec.MachineName, |
99 | 102 | Source = rec.ProviderName, |
@@ -109,8 +112,7 @@ | ||
109 | 112 | { |
110 | 113 | try { |
111 | 114 | return rec.FormatDescription(); |
112 | - } | |
113 | - catch(Exception ex) { | |
115 | + } catch (Exception ex) { | |
114 | 116 | log.Error("format error", ex); |
115 | 117 | return "---"; |
116 | 118 | } |
@@ -23,13 +23,17 @@ | ||
23 | 23 | /// </summary> |
24 | 24 | public class FileWatcher : BaseWatcher |
25 | 25 | { |
26 | + private Configuration.GeneralConfiguration generalConf; | |
26 | 27 | private string path; |
27 | 28 | private Encoding encoding; |
28 | 29 | private long position = -1; |
29 | 30 | private bool successRead = true; |
30 | 31 | |
31 | - public FileWatcher(string path, Encoding encoding, List<ActionTable> actionTable) : base(actionTable) | |
32 | + public FileWatcher(Configuration.GeneralConfiguration generalConf, | |
33 | + string path, Encoding encoding, List<ActionTable> actionTable) | |
34 | + : base(actionTable) | |
32 | 35 | { |
36 | + this.generalConf = generalConf; | |
33 | 37 | this.path = path; |
34 | 38 | this.encoding = encoding; |
35 | 39 | } |
@@ -37,33 +41,34 @@ | ||
37 | 41 | public override void Watch() |
38 | 42 | { |
39 | 43 | try { |
40 | - using(FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){ | |
44 | + using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { | |
41 | 45 | fs.Seek(0, SeekOrigin.End); |
42 | - if(position < 0){ | |
46 | + if (position < 0) { | |
43 | 47 | position = fs.Position; |
44 | - } | |
45 | - else{ | |
46 | - if(position > fs.Position){ | |
48 | + } else { | |
49 | + if (position > fs.Position) { | |
47 | 50 | position = 0; |
48 | 51 | } |
49 | 52 | fs.Seek(position, SeekOrigin.Begin); |
50 | - using(StreamReader sr = new StreamReader(fs, encoding)){ | |
53 | + using (StreamReader sr = new StreamReader(fs, encoding)) { | |
51 | 54 | string preReadLine = null; |
52 | - while(!sr.EndOfStream || preReadLine != null){ | |
55 | + while (!sr.EndOfStream || preReadLine != null) { | |
53 | 56 | string line = preReadLine ?? sr.ReadLine(); |
54 | 57 | preReadLine = null; |
55 | 58 | var data = new LogData { |
59 | + Name = generalConf != null ? generalConf.Name : null, | |
56 | 60 | TimeStamp = DateTime.Now, |
57 | 61 | HostName = Environment.MachineName, |
58 | 62 | Source = path, |
59 | 63 | Message = line, |
64 | + Level = line.ToLower().Contains("error") ? "E" : "W" | |
60 | 65 | }; |
61 | 66 | var table = LogMatcher.Match(actionTable, data); |
62 | - if(table != null) { | |
63 | - if(!string.IsNullOrEmpty(table.WhilePattern)){ | |
67 | + if (table != null) { | |
68 | + if (!string.IsNullOrEmpty(table.WhilePattern)) { | |
64 | 69 | var lines = new List<string>(); |
65 | 70 | preReadLine = PreRead(sr, lines, table.WhilePattern, table.WhileMax, 500); |
66 | - if(!Util.IsNullOrEmpty(lines)){ | |
71 | + if (!Util.IsNullOrEmpty(lines)) { | |
67 | 72 | data.Message = string.Join("\n", data.Message, string.Join("\n", lines)); |
68 | 73 | } |
69 | 74 | } |
@@ -75,9 +80,8 @@ | ||
75 | 80 | } |
76 | 81 | } |
77 | 82 | successRead = true; |
78 | - } | |
79 | - catch(Exception ex){ | |
80 | - if(successRead){ | |
83 | + } catch (Exception ex) { | |
84 | + if (successRead) { | |
81 | 85 | log.WarnFormat("Read error : {0}({1})", ex.Message, path); |
82 | 86 | successRead = false; |
83 | 87 | } |
@@ -90,10 +94,10 @@ | ||
90 | 94 | var timeout = DateTime.Now.AddMilliseconds(timeoutMilliSec); |
91 | 95 | var count = 0; |
92 | 96 | |
93 | - while(DateTime.Now.CompareTo(timeout) < 0){ | |
94 | - while(!sr.EndOfStream && (max == null || count < max)){ | |
97 | + while (DateTime.Now.CompareTo(timeout) < 0) { | |
98 | + while (!sr.EndOfStream && (max == null || count < max)) { | |
95 | 99 | var line = sr.ReadLine(); |
96 | - if(!regex.IsMatch(line)){ | |
100 | + if (!regex.IsMatch(line)) { | |
97 | 101 | return line; |
98 | 102 | } |
99 | 103 | buffer.Add(line); |
@@ -24,13 +24,17 @@ | ||
24 | 24 | /// </summary> |
25 | 25 | public class SyslogServer : BaseWatcher |
26 | 26 | { |
27 | + private Configuration.GeneralConfiguration generalConf; | |
27 | 28 | private bool stopRunning; |
28 | 29 | private Thread listener; |
29 | 30 | private int listenPort; |
30 | 31 | |
31 | - public SyslogServer(string port, List<ActionTable> actionTable) : base(actionTable) | |
32 | + public SyslogServer(Configuration.GeneralConfiguration generalConf, | |
33 | + string port, List<ActionTable> actionTable) | |
34 | + : base(actionTable) | |
32 | 35 | { |
33 | - if(!int.TryParse(port, out listenPort)){ | |
36 | + this.generalConf = generalConf; | |
37 | + if (!int.TryParse(port, out listenPort)) { | |
34 | 38 | listenPort = 514; |
35 | 39 | } |
36 | 40 | stopRunning = false; |
@@ -55,22 +59,19 @@ | ||
55 | 59 | UdpClient udpListener = new UdpClient(listenPort); |
56 | 60 | byte[] receiveData; |
57 | 61 | |
58 | - while(!stopRunning){ | |
62 | + while (!stopRunning) { | |
59 | 63 | try { |
60 | 64 | udpListener.Client.ReceiveTimeout = 1000; |
61 | 65 | receiveData = udpListener.Receive(ref endPoint); |
62 | 66 | string data = Encoding.UTF8.GetString(receiveData); |
63 | 67 | HandleLog(data); |
64 | - } | |
65 | - catch(SocketException) { | |
68 | + } catch (SocketException) { | |
66 | 69 | continue; |
67 | - } | |
68 | - catch(Exception ex) { | |
70 | + } catch (Exception ex) { | |
69 | 71 | log.ErrorFormat("Receive error : {0}", ex.Message); |
70 | 72 | } |
71 | 73 | } |
72 | - } | |
73 | - catch(Exception ex) { | |
74 | + } catch (Exception ex) { | |
74 | 75 | log.ErrorFormat("abort : {0}", ex.Message); |
75 | 76 | } |
76 | 77 | } |
@@ -79,18 +80,18 @@ | ||
79 | 80 | { |
80 | 81 | data = data.Replace("\r", "").Replace("\n", ""); |
81 | 82 | Match match = Regex.Match(data, "<([0-9]+)>([A-Za-z]{3} [ 0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}) ([^ ]+) (.*)"); |
82 | - if(match != null && match.Groups.Count==5){ | |
83 | + if (match != null && match.Groups.Count == 5) { | |
83 | 84 | int priority; |
84 | 85 | int.TryParse(match.Groups[1].Value, out priority); |
85 | - FindAndExecute(new LogData{ | |
86 | - TimeStamp = GetTimeStamp(match.Groups[2].Value), | |
87 | - HostName = match.Groups[3].Value, | |
88 | - Message = match.Groups[4].Value, | |
89 | - Level = GetLevel(priority % 8), | |
90 | - Source = GetFacilityName(priority / 8), | |
91 | - }); | |
92 | - } | |
93 | - else{ | |
86 | + FindAndExecute(new LogData { | |
87 | + Name = generalConf != null ? generalConf.Name : null, | |
88 | + TimeStamp = GetTimeStamp(match.Groups[2].Value), | |
89 | + HostName = match.Groups[3].Value, | |
90 | + Message = match.Groups[4].Value, | |
91 | + Level = GetLevel(priority % 8), | |
92 | + Source = GetFacilityName(priority / 8), | |
93 | + }); | |
94 | + } else { | |
94 | 95 | log.ErrorFormat("Invalid log received : {0}", data); |
95 | 96 | } |
96 | 97 | } |
@@ -99,14 +100,15 @@ | ||
99 | 100 | { |
100 | 101 | DateTime result = DateTime.Now; |
101 | 102 | Match match = Regex.Match(dateString, "([A-Za-z]{3}) ([ 0-9]{2}) ([0-9]{2}:[0-9]{2}:[0-9]{2})"); |
102 | - if(match != null && match.Groups.Count==4){ | |
103 | + if (match != null && match.Groups.Count == 4) { | |
103 | 104 | int month, day; |
104 | 105 | month = Util.GetMonthFromString(match.Groups[1].Value); |
105 | - if(month == 0) month = DateTime.Now.Month; | |
106 | + if (month == 0) | |
107 | + month = DateTime.Now.Month; | |
106 | 108 | int.TryParse(match.Groups[2].Value, out day); |
107 | 109 | result = DateTime.Parse(match.Groups[3].Value); |
108 | 110 | result = new DateTime(result.Year, month, day, result.Hour, result.Minute, result.Second); |
109 | - if(result.Month==12 && DateTime.Now.Month==1){ | |
111 | + if (result.Month == 12 && DateTime.Now.Month == 1) { | |
110 | 112 | result.AddYears(-1); |
111 | 113 | } |
112 | 114 | } |
@@ -116,23 +118,23 @@ | ||
116 | 118 | private string GetLevel(int severity) |
117 | 119 | { |
118 | 120 | string result = null; |
119 | - switch(severity){ | |
120 | - case 0: /* EMERGENCY */ | |
121 | - case 1: /* ALERT */ | |
122 | - case 2: /* CRITICAL */ | |
123 | - case 3: /* ERROR */ | |
124 | - result = "E"; | |
125 | - break; | |
126 | - case 4: /* WARNING */ | |
127 | - result = "W"; | |
128 | - break; | |
129 | - case 5: /* NOTICE */ | |
130 | - case 6: /* INFORMATION */ | |
131 | - result = "I"; | |
132 | - break; | |
133 | - case 7: /* DEBUG */ | |
134 | - result = "D"; | |
135 | - break; | |
121 | + switch (severity) { | |
122 | + case 0: /* EMERGENCY */ | |
123 | + case 1: /* ALERT */ | |
124 | + case 2: /* CRITICAL */ | |
125 | + case 3: /* ERROR */ | |
126 | + result = "E"; | |
127 | + break; | |
128 | + case 4: /* WARNING */ | |
129 | + result = "W"; | |
130 | + break; | |
131 | + case 5: /* NOTICE */ | |
132 | + case 6: /* INFORMATION */ | |
133 | + result = "I"; | |
134 | + break; | |
135 | + case 7: /* DEBUG */ | |
136 | + result = "D"; | |
137 | + break; | |
136 | 138 | } |
137 | 139 | return result; |
138 | 140 | } |
@@ -165,7 +167,7 @@ | ||
165 | 167 | "local6", |
166 | 168 | "local7", |
167 | 169 | }; |
168 | - if(facility >= 0 && facility < names.Length){ | |
170 | + if (facility >= 0 && facility < names.Length) { | |
169 | 171 | return names[facility]; |
170 | 172 | } |
171 | 173 | return null; |
@@ -77,7 +77,7 @@ | ||
77 | 77 | #if _WINDOWS |
78 | 78 | Dictionary<string, List<ActionTable>> eventlogs = config.EventLog; |
79 | 79 | foreach (string name in eventlogs.Keys) { |
80 | - BaseWatcher watcher = new EventLogWatcher(name, eventlogs[name]); | |
80 | + BaseWatcher watcher = new EventLogWatcher(config.General, name, eventlogs[name]); | |
81 | 81 | watchers.Add(watcher); |
82 | 82 | } |
83 | 83 | #endif |
@@ -84,12 +84,12 @@ | ||
84 | 84 | Dictionary<string,List<ActionTable>> files = config.File; |
85 | 85 | foreach(string path in files.Keys){ |
86 | 86 | var fileAndEncoding = FileAndEncoding.Parse(path); |
87 | - BaseWatcher watcher = new FileWatcher(fileAndEncoding.File, fileAndEncoding.Encoding, files[path]); | |
87 | + BaseWatcher watcher = new FileWatcher(config.General, fileAndEncoding.File, fileAndEncoding.Encoding, files[path]); | |
88 | 88 | watchers.Add(watcher); |
89 | 89 | } |
90 | 90 | Dictionary<string,List<ActionTable>> syslogs = config.Syslog; |
91 | 91 | foreach(string port in syslogs.Keys){ |
92 | - BaseWatcher watcher = new SyslogServer(port, syslogs[port]); | |
92 | + BaseWatcher watcher = new SyslogServer(config.General, port, syslogs[port]); | |
93 | 93 | watchers.Add(watcher); |
94 | 94 | } |
95 | 95 | } |
@@ -30,7 +30,7 @@ | ||
30 | 30 | "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"+ |
31 | 31 | "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890"+ |
32 | 32 | "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", |
33 | - new MailAddress("test@test.com"), new MailAddress[]{ new MailAddress("test@test.com") }, null, null); | |
33 | + new MailAddress("test@test.com"), new MailAddress[]{ new MailAddress("test@test.com") }, null, null, false); | |
34 | 34 | |
35 | 35 | } |
36 | 36 | } |