Index: trunk/src/org/openstreetmap/josm/gui/ExceptionDialogUtil.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/ExceptionDialogUtil.java	(revision 14809)
+++ trunk/src/org/openstreetmap/josm/gui/ExceptionDialogUtil.java	(revision 14810)
@@ -335,5 +335,5 @@
         String body = e.getErrorBody();
         Object msg = null;
-        if ("text/html".equals(e.getContentType()) && body != null && body.startsWith("<") && body.contains("<html>")) {
+        if (e.isHtml() && body != null && body.startsWith("<") && body.contains("<html>")) {
             msg = new HtmlPanel(body);
         } else {
Index: trunk/src/org/openstreetmap/josm/io/OsmApiException.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmApiException.java	(revision 14809)
+++ trunk/src/org/openstreetmap/josm/io/OsmApiException.java	(revision 14810)
@@ -4,4 +4,5 @@
 
 import org.openstreetmap.josm.tools.Logging;
+import org.openstreetmap.josm.tools.Utils;
 
 /**
@@ -32,8 +33,9 @@
         this.responseCode = responseCode;
         this.errorHeader = errorHeader;
-        this.errorBody = errorBody;
+        this.errorBody = Utils.strip(errorBody);
         this.accessedUrl = accessedUrl;
         this.login = login;
         this.contentType = contentType;
+        checkHtmlBody();
     }
 
@@ -111,4 +113,13 @@
     public OsmApiException(String message, Throwable cause) {
         super(message, cause);
+    }
+
+    private void checkHtmlBody() {
+        if (errorBody != null && errorBody.matches("^<.*>.*<.*>$")) {
+            setContentType("text/html");
+            if (!errorBody.contains("<html>")) {
+                errorBody = "<html>" + errorBody + "</html>";
+            }
+        }
     }
 
@@ -268,3 +279,12 @@
         return contentType;
     }
+
+    /**
+     * Determines if the exception has {@code text/html} as content type.
+     * @return {@code true} if the exception has {@code text/html} as content type.
+     * @since xxx
+     */
+    public final boolean isHtml() {
+        return "text/html".equals(contentType);
+    }
 }
Index: trunk/test/unit/org/openstreetmap/josm/io/OsmApiExceptionTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/io/OsmApiExceptionTest.java	(revision 14810)
+++ trunk/test/unit/org/openstreetmap/josm/io/OsmApiExceptionTest.java	(revision 14810)
@@ -0,0 +1,33 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.io;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.openstreetmap.josm.testutils.JOSMTestRules;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+
+/**
+ * Unit tests of {@link OsmApiException} class.
+ */
+public class OsmApiExceptionTest {
+
+    /**
+     * Setup tests
+     */
+    @Rule
+    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
+    public JOSMTestRules test = new JOSMTestRules().preferences();
+
+    /**
+     * Non-regression test for <a href="https://josm.openstreetmap.de/ticket/17328">Bug #17328</a>.
+     */
+    @Test
+    public void testTicket17328() {
+        assertFalse(new OsmApiException(503, "foo", "bar").isHtml());
+        assertTrue(new OsmApiException(503, null, "<h2>This website is under heavy load (queue full)</h2><p>Sorry...</p>").isHtml());
+    }
+}
